如何在Spring Boot中配置多个安全上下文?

时间:2019-07-16 13:54:09

标签: java spring-boot spring-security

我正在使用Spring Security运行Spring-Boot 2应用程序。我希望应用程序独立处理不同路径的安全性,例如:

  • 我想对/api-spec/**(仅此路径)使用基本身份验证
  • 以及/api/**的自定义JWT身份验证

我的所有尝试都导致为整个应用程序而不是/api-spec/**启用了基本身份验证,这绝对不是我想要的。

我的安全配置如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable().authorizeRequests()
            .antMatchers(HttpMethod.GET, "/api-spec/**")
            .authenticated().and().httpBasic()
            .and().authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .addFilter(new JwtAuthenticationFilter(...))
            .addFilter(new JwtAuthorizationFilter(...))
            .httpBasic().disable();
}

我还尝试了多个WebSecurityConfigurerAdapter运气,效果相同。

是否可以告诉Spring将不同的安全上下文用于不同的路径?

1 个答案:

答案 0 :(得分:0)

您必须自定义JWT,使其仅适用于请求/api-spec/**

  

我所有的尝试都导致为   整个应用程序,而不仅仅是/ api-spec / **

您有.antMatchers(HttpMethod.GET, "/api-spec/**").authenticated()这是基本的 身份验证,但您未指定对/api/**执行的操作。由于您拥有.anyRequest().authenticated(),因此 Spring将验证来自/api/**的所有请求(此处为所有请求)


JWT自定义(只是一个我不知道的关于.addFilter(new JwtAuthenticationFilter(...))的想法)

仅对于包含/api/** 的请求,才需要JWT令牌 /api-spec/**/不需要JWT令牌。达到要求的代码是

//JwtAuthenticationEntryPoint.java
if(request.getRequestURI().contains("api-spec")==true)
{
    System.out.println("JWT Token is not required");
    chain.doFilter(request, response);
}

//JwtRequestFilter.java
if(request.getRequestURI().contains("api-spec")==false) 
      response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); 

JwtAuthenticationEntryPoint.java

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {

    private static final long serialVersionUID = -7858869558953243875L;

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException {

        System.out.println("Entry Request: "+request.getRequestURI());
        System.out.println("Entry Contain: "+request.getRequestURI().contains("api-spec"));
        if(request.getRequestURI().contains("api-spec")==false) 
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");    
    }
}

JwtRequestFilter.java

@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        final String requestTokenHeader = request.getHeader("Authorization");
        System.out.println("JWT Request: "+request.getRequestURI());
        System.out.println("JWT Contain: "+request.getRequestURI().contains("api-spec"));
        String username = null;
        String jwtToken = null;

        if(request.getRequestURI().contains("api-spec")==true)
        {
            System.out.println("JWT Token is not required");
            chain.doFilter(request, response);
        }
        else 
            if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ") ) {
            jwtToken = requestTokenHeader.substring(7);
            try {
                username = jwtTokenUtil.getUsernameFromToken(jwtToken);
            } catch (IllegalArgumentException e) {
                System.out.println("Unable to get JWT Token");
            } catch (ExpiredJwtException e) {
                System.out.println("JWT Token has expired");
            }
        } else {
            logger.warn("JWT Token does not begin with Bearer String");
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);

            if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {

                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request, response);
    }

}