简体   繁体   中英

How to configure multiple security contexts in Spring Boot?

I'm running a Spring-Boot 2 application with Spring Security. I want the application to independently handle security for different paths, let's say:

  • I want to use basic authentication for /api-spec/** (and only this path)
  • And a custom JWT authentication for /api/**

All my attempts led to basic authentication being enabled for the whole application and not only for /api-spec/** , which is definitely not what I want.

My security configuration looks like this:

@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();
}

I also tried my luck with multiple WebSecurityConfigurerAdapter s, which had the same effect.

Is it possible to tell Spring to use separate security contexts for different paths?

You have to customize JWT to apply only for request /api-spec/**

All my attempts led to basic authentication being enabled for the whole application and not only for /api-spec/**

you have .antMatchers(HttpMethod.GET, "/api-spec/**").authenticated() which is for basic authentication but you didn't specify what to do for /api/** . As you have .anyRequest().authenticated() so Spring will authenticated all request from /api/** (here all request)


JWT Customization (just an idea as I don't know about .addFilter(new JwtAuthenticationFilter(...)))

Here JWT Token will be required only for a request which contains /api/** for /api-spec/**/ JWT Token is not required. Code that achieves the requirement is

//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);
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM