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

基于Sling Filter验证Okta登录状态:AEM 6.5 React SPA集成求助

Okta登录集成至AEM 6.5 React SPA站点(Sling Filter验证方案)

1. 引入Okta Java SDK依赖

在AEM项目的pom.xml中添加Okta JWT验证相关依赖:

<dependency>
    <groupId>com.okta.jwt</groupId>
    <artifactId>okta-jwt-verifier</artifactId>
    <version>2.0.7</version> <!-- 使用最新稳定版 -->
</dependency>
<dependency>
    <groupId>com.okta.spring</groupId>
    <artifactId>okta-spring-sdk</artifactId>
    <version>2.1.6</version>
</dependency>

2. 编写Sling Filter实现登录验证

创建OSGi组件形式的Sling Filter,拦截受保护资源请求并验证Okta Token有效性:

2.1 Filter核心代码

import com.okta.jwt.Jwt;
import com.okta.jwt.JwtVerifier;
import com.okta.jwt.JwtVerifierBuilder;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.filter.AbstractSlingFilter;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import java.io.IOException;

@Component(
        service = javax.servlet.Filter.class,
        property = {
                "sling.filter.scope=REQUEST",
                "sling.filter.pattern=/content/your-spa-site/.*", // 替换为你的SPA内容路径
                "service.ranking:Integer=1000" // 确保Filter在默认认证Filter前执行
        }
)
@Designate(ocd = OktaFilterConfig.class)
public class OktaAuthFilter extends AbstractSlingFilter {

    private OktaFilterConfig config;
    private JwtVerifier jwtVerifier;

    @Override
    protected void doFilter(SlingHttpServletRequest request, SlingHttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 1. 从Header或Cookie提取Okta Token
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
        } else {
            token = request.getCookie("okta-id-token") != null ? request.getCookie("okta-id-token").getValue() : null;
        }

        // 2. 验证Token有效性
        if (token == null || !validateToken(token)) {
            response.sendRedirect(config.oktaLoginUrl());
            return;
        }

        // 3. 验证通过,放行请求
        chain.doFilter(request, response);
    }

    private boolean validateToken(String token) {
        try {
            // 根据实际使用的Token类型选择decodeIdToken或decodeAccessToken
            Jwt jwt = jwtVerifier.decodeIdToken(token);
            // 额外验证受众和发行方(SDK已默认基础验证,此处为增强校验)
            return jwt.getAudience().contains(config.oktaAudience()) &&
                    jwt.getIssuer().equals(config.oktaIssuer());
        } catch (Exception e) {
            // Token过期、签名无效等情况均返回验证失败
            return false;
        }
    }

    @Override
    protected void activate(OktaFilterConfig config) {
        this.config = config;
        try {
            this.jwtVerifier = new JwtVerifierBuilder()
                    .setIssuer(config.oktaIssuer())
                    .setClientId(config.oktaClientId())
                    .setAudience(config.oktaAudience())
                    .setConnectionTimeout(3000)
                    .build();
        } catch (Exception e) {
            throw new RuntimeException("初始化Okta JWT验证器失败", e);
        }
    }

    @ObjectClassDefinition(name = "Okta认证过滤器配置")
    public @interface OktaFilterConfig {
        @AttributeDefinition(name = "Okta租户发行方", description = "示例:https://your-okta-domain.com/oauth2/default")
        String oktaIssuer();

        @AttributeDefinition(name = "Okta客户端ID")
        String oktaClientId();

        @AttributeDefinition(name = "Okta受众", description = "Token的受众,通常为客户端ID或API受众")
        String oktaAudience();

        @AttributeDefinition(name = "Okta独立登录页地址")
        String oktaLoginUrl();
    }
}

3. OSGi配置步骤

  1. 登录AEM控制台(/system/console/configMgr)
  2. 找到Okta认证过滤器配置项
  3. 填入你的Okta租户信息:
    • Okta租户发行方:你的Okta OAuth2 issuer地址
    • Okta客户端ID:Okta控制台创建的SPA应用Client ID
    • Okta受众:对应Token的受众值
    • Okta独立登录页地址:你已托管的Okta登录页URL

4. React SPA端配合处理

  • 登录成功后,将Okta返回的Id Token写入带HttpOnly、Secure属性的Cookie,避免XSS风险:
// 登录成功回调中获取Id Token后执行
document.cookie = `okta-id-token=${idToken}; path=/; HttpOnly; Secure; SameSite=Strict`;
  • 浏览器会自动在同域请求中携带该Cookie,无需额外处理

关键注意事项

  • Token过期处理:Filter捕获Token过期异常时,直接重定向到Okta登录页重新获取Token
  • Filter顺序:通过service.ranking属性确保该Filter在AEM默认SlingAuthenticator之前执行,避免默认认证逻辑干扰
  • HTTPS要求:生产环境必须启用HTTPS,确保Token传输安全,Cookie的Secure属性生效

内容的提问来源于stack exchange,提问作者Ashish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:30:11