【问题标题】:How to validate a custom session in spring如何在春季验证自定义会话
【发布时间】:2021-12-30 07:02:05
【问题描述】:

我是 spring 新手,所以只是在寻找一个大致的方向/建议。

我正在构建一个小型微服务。服务身份验证已设置为验证传递给它的 JWT(由不同的微服务发布)。

JWT 包含一个 sessionid 声明。我希望能够获得该声明,并验证会话是否仍处于活动状态。

目前将通过直接查询数据库,尽管将来当我们有专用会话服务时,我会将其更改为调用该服务。

我显然可以在每个应该验证会话的控制器中获得声明(基本上所有这些),但我正在寻找一个更全局的选项,例如请求拦截器(仅在 JWT 验证后触发,并且具有访问经过验证的 JWT)。

有没有推荐的方式在春天做这种事情?

【问题讨论】:

  • SecurityContextHolder.getContext() --> 你有没有试过把它变成一个变量并在它的方法中打点?
  • @Llama 有一个很好的建议。如果您访问Authentication,它有一个principal,它是一个Jwt,让您无需双重解析JWT即可访问声明。结合下面的答案,您可以在BearerTokenAuthenticationFilter 之后放置一个自定义过滤器。另请查看JwtAuthenticationConverter(请参阅docs)。您可以生成 JwtAuthenticationToken 的自定义扩展,其中包含您的自定义声明作为字段。

标签: java spring spring-boot session spring-security


【解决方案1】:

您有几种选择:使用ControllerAdvice,也许是 AOP,但可能要走的路是使用自定义安全过滤器。

this articlethis related SO question 举例说明了这个想法。

首先,创建一个过滤器来处理相应的声明。例如:

public class SessionValidationFilter extends GenericFilterBean {

  private static final String AUTHORIZATION_HEADER = "Authorization";
  private static final String AUTHORIZATION_BEARER = "Bearer";

  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
    throws IOException, ServletException {
    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
    // We will provide our own validation logic from scratch
    // If you are using Spring OAuth or something similar 
    // you can instead use the already authenticated token, something like:
    // Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    // if (authentication != null && authentication.getPrincipal() instanceof Jwt) {
    //    Jwt jwt = (Jwt) authentication.getPrincipal();
    //    String sessionId = jwt.getClaimAsString("sessionid");
    //    ...
    
    // Resolve token from request
    String jwt = getTokenFromRequest(httpServletRequest);
    if (jwt == null) {
       // your choice... mine
       filterChain.doFilter(servletRequest, servletResponse);
       return;
    }

    // If the token is not valid, raise error
    if (!this.validateToken(jwt)) {
      throw new BadCredentialsException("Session expired");
    }

    // Continue filter chain
    filterChain.doFilter(servletRequest, servletResponse);
  }

  // Resolve token from Authorization header
  private String getTokenFromRequest(HttpServletRequest request){
    String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
    if (StringUtils.isNotEmpty(bearerToken) && bearerToken.startsWith(AUTHORIZATION_BEARER)) {
      return bearerToken.substring(7, bearerToken.length());
    }
    return null;
  }

  // Validate the JWT token
  // We can use the jjwt library, for instance, to process the JWT token claims
  private boolean validateToken(String token) {
    try {
      Claims claims = Jwts.parser()
        // .setSigningKey(...)
        .parseClaimsJws(token)
        .getBody()
      ;

      String sessionId = (String)claims.get("sessionid"); 
      // Process as appropriate to determine whether the session is valid or not
      //...

      return true;
    } catch (Exception e) {
      // consider logging the error. Handle as appropriate
    }

    return false;
  }
}

现在,假设您正在使用 Java 配置,将过滤器添加到 Spring Security 过滤器链中实际执行身份验证的过滤器链之后:

@Configuration
public class SecurityConfiguration
  extends WebSecurityConfigurerAdapter {

  // the rest of your code

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    // the rest of your configuration

    // Add the custom filter
    // see https://docs.spring.io/spring-security/site/docs/5.2.1.RELEASE/reference/htmlsingle/#filter-stack
    // you can name every provided filter or any specified that is included in the filter chain
    http.addFilterAfter(new SessionValidationFilter(), BasicAuthenticationFilter.class);
  }
}

【讨论】:

  • 谢谢先生!这很有帮助。看起来我现在走在正确的轨道上。
  • 欢迎您@BoomShaka。我很乐意提供帮助。
猜你喜欢
  • 2017-03-02
  • 1970-01-01
  • 2017-03-05
  • 2013-02-24
  • 1970-01-01
  • 1970-01-01
  • 2017-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多