You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 12:14:35