基于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配置步骤
- 登录AEM控制台(
/system/console/configMgr) - 找到
Okta认证过滤器配置项 - 填入你的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
相关产品推荐
相关产品推荐

