基于JSP/Servlet的传统应用使用MSAL4J对接Azure AD B2C的示例需求
基于JSP/Servlet的传统应用使用MSAL4J对接Azure AD B2C的示例需求
当然有办法!我之前帮过好几个遗留JSP/Servlet项目对接Azure AD B2C,用MSAL4J完全不需要依赖Spring Boot,纯Servlet生态就能搞定。下面我给你梳理核心步骤和关键代码片段,直接就能套进你的项目里:
1. 先搞定MSAL4J依赖
如果你的项目用Maven管理,直接在pom.xml里加这个依赖:
<dependency> <groupId>com.microsoft.azure</groupId> <artifactId>msal4j</artifactId> <version>1.24.0</version> <!-- 建议用最新稳定版 --> </dependency>
要是不用Maven,就去MSAL4J的官方仓库下载jar包,手动放到项目的WEB-INF/lib目录里就行。
2. 配置AD B2C核心参数
先把AD B2C的关键配置抽成常量或者放在配置文件里(比如web.xml的context-param),方便后续调用:
public class ADBC2Config { // 替换成你的租户ID,比如xxx.onmicrosoft.com public static final String TENANT_ID = "your-tenant-id"; // 替换成你的应用注册客户端ID public static final String CLIENT_ID = "your-client-id"; // 替换成你的应用注册客户端密钥 public static final String CLIENT_SECRET = "your-client-secret"; // AD B2C授权端点格式:https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy-name}/oauth2/v2.0/authorize public static final String AUTHORITY = "https://your-tenant.b2clogin.com/your-tenant.onmicrosoft.com/B2C_1_signupsignin1"; // 替换成你的回调地址,要和应用注册里配置的一致,比如http://localhost:8080/your-app/auth/callback public static final String REDIRECT_URI = "your-redirect-uri"; // 所需的权限,根据你的需求调整 public static final String[] SCOPES = {"openid", "profile", "email"}; }
3. 写授权跳转的Servlet
创建一个AuthInitiateServlet,用来处理用户的登录请求,跳转到AD B2C的授权页面:
@WebServlet("/auth/login") public class AuthInitiateServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 初始化机密客户端应用 ConfidentialClientApplication client = ConfidentialClientApplication.builder( ADBC2Config.CLIENT_ID, ClientCredentialFactory.createFromSecret(ADBC2Config.CLIENT_SECRET)) .authority(ADBC2Config.AUTHORITY) .build(); // 构建授权请求参数 AuthorizationRequestUrlParameters authParams = AuthorizationRequestUrlParameters.builder( ADBC2Config.REDIRECT_URI, Arrays.asList(ADBC2Config.SCOPES)) .responseMode(ResponseMode.FORM_POST) // 或者用QUERY,看你的需求 .prompt(Prompt.SELECT_ACCOUNT) // 强制用户选择账号,可选 .build(); // 生成AD B2C的授权URL,并重定向过去 String authUrl = client.getAuthorizationRequestUrl(authParams).toString(); response.sendRedirect(authUrl); } catch (MalformedURLException e) { throw new ServletException("Invalid AD B2C authority URL", e); } } }
4. 处理AD B2C的回调Servlet
创建AuthCallbackServlet,接收AD B2C返回的授权码,然后用MSAL4J交换令牌:
@WebServlet("/auth/callback") public class AuthCallbackServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String authCode = request.getParameter("code"); if (authCode == null || authCode.isEmpty()) { // 处理授权失败的情况,比如跳转到错误页面 response.sendRedirect("/error.jsp"); return; } try { ConfidentialClientApplication client = ConfidentialClientApplication.builder( ADBC2Config.CLIENT_ID, ClientCredentialFactory.createFromSecret(ADBC2Config.CLIENT_SECRET)) .authority(ADBC2Config.AUTHORITY) .build(); // 构建授权码参数,交换令牌 AuthorizationCodeParameters tokenParams = AuthorizationCodeParameters.builder( authCode, new URI(ADBC2Config.REDIRECT_URI)) .scopes(Arrays.asList(ADBC2Config.SCOPES)) .build(); // 获取令牌结果 IAuthenticationResult result = client.acquireToken(tokenParams).join(); // 把令牌和用户信息存在session里,方便后续使用 HttpSession session = request.getSession(); session.setAttribute("idToken", result.idToken()); session.setAttribute("accessToken", result.accessToken()); session.setAttribute("userName", result.account().username()); // 跳转到应用的主页或者用户需要访问的页面 response.sendRedirect("/home.jsp"); } catch (Exception e) { throw new ServletException("Failed to acquire token from AD B2C", e); } } }
5. 在JSP里验证和使用用户信息
比如在home.jsp里,你可以从session中取出用户信息,判断是否登录:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Home Page</title> </head> <body> <% String userName = (String) session.getAttribute("userName"); if (userName == null) { // 未登录,跳转到登录页面 response.sendRedirect("/auth/login"); return; } %> <h1>Welcome, <%= userName %>!</h1> <p>Your ID Token: <%= session.getAttribute("idToken") %></p> <a href="/auth/logout">Logout</a> </body> </html>
额外注意事项
- 一定要确保应用注册里的重定向URI和你代码里的
REDIRECT_URI完全一致,包括HTTP/HTTPS、端口和路径 - 令牌过期后,可以用MSAL4J的
acquireTokenSilently方法自动刷新,避免用户重复登录 - 生产环境里不要把客户端密钥硬编码在代码里,建议放在环境变量或者加密的配置文件中
- 记得处理各种异常情况,比如授权被拒绝、网络错误等
备注:内容来源于stack exchange,提问作者Aldo Inácio da Silva
相关产品推荐
相关产品推荐

