我正在使用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将不同的安全上下文用于不同的路径?
答案 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);
}
}