Spring boot 使用JWT的Spring安全性,如何从使用JwtAuthenticationFilter的身份验证中排除某些端点,如/login?
我想将/login url从spring security的身份验证中排除。 我的配置类看起来像'Spring boot 使用JWT的Spring安全性,如何从使用JwtAuthenticationFilter的身份验证中排除某些端点,如/login?,spring-boot,spring-security,jwt,Spring Boot,Spring Security,Jwt,我想将/login url从spring security的身份验证中排除。 我的配置类看起来像' @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests().antMatchers("/v1/pricing/login").permitAll()
.antMatchers("v1/pricing/**").authenticated().and()
.addFilterBefore(corsFilter,UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/v1/pricing/login");
}
JwtAuthenticationFilter看起来像
-注释了异常部分,因为它也开始在登录时抛出异常
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
@Autowired
JwtTokenProvider jwtTokenProvider;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String jwt = getJwtFromRequest(request);
if (StringUtils.hasText(jwt) && jwtTokenProvider.validateToken(jwt)) {
String[] userInfo = jwtTokenProvider.getUserDetailsFromJWT(jwt);
UserDetails userDetails = new UserPrincipal(Long.parseLong(userInfo[0]), userInfo[1], userInfo[2], null,
userInfo[3]);
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(userDetails, null, null);
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
filterChain.doFilter(request, response);
}
private String getJwtFromRequest(HttpServletRequest request) {
String token = request.getHeader("Authorization");
if (StringUtils.hasText(token)) {
return token;
} /*else {
throw new AuthenticationServiceException("Authorization header cannot be blank!");
}*/
return null;
}
}
任何带有/v1/pricing/login的请求仍然会转到JWtAuthentication筛选器并失败 JwtTokenAuthenticationProcessingFilter筛选器配置为跳过以下端点:/api/auth/login和/api/auth/token。这是通过RequestMatcher的SkipPathRequestMatcher实现实现的
public class SkipPathRequestMatcher implements RequestMatcher {
private OrRequestMatcher matchers;
private RequestMatcher processingMatcher;
public SkipPathRequestMatcher(List<String> pathsToSkip, String processingPath) {
Assert.notNull(pathsToSkip);
List<RequestMatcher> m = pathsToSkip.stream().map(path -> new AntPathRequestMatcher(path)).collect(Collectors.toList());
matchers = new OrRequestMatcher(m);
processingMatcher = new AntPathRequestMatcher(processingPath);
}
@Override
public boolean matches(HttpServletRequest request) {
if (matchers.matches(request)) {
return false;
}
return processingMatcher.matches(request) ? true : false;
}
}
公共类SkipPathRequestMatcher实现RequestMatcher{
私人或请求匹配者;
私有请求匹配器处理匹配器;
公共SkipPathRequestMatcher(列表路径跳过,字符串处理路径){
Assert.notNull(路径跳过);
List m=pathsToSkip.stream().map(路径->新建AntPathRequestMatcher(路径)).collect(收集器.toList());
匹配器=新匹配器或请求匹配器(m);
processingMatcher=新的AntPathRequestMatcher(processingPath);
}
@凌驾
公共布尔匹配(HttpServletRequest){
if(matchers.matches(请求)){
返回false;
}
返回processingMatcher.matches(请求)?true:false;
}
}
然后打电话:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public static final String JWT_TOKEN_HEADER_PARAM = "X-Authorization";
public static final String FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login";
public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**";
public static final String TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token";
protected JwtTokenAuthenticationProcessingFilter buildJwtTokenAuthenticationProcessingFilter() throws Exception {
List<String> pathsToSkip = Arrays.asList(TOKEN_REFRESH_ENTRY_POINT, FORM_BASED_LOGIN_ENTRY_POINT);
SkipPathRequestMatcher matcher = new SkipPathRequestMatcher(pathsToSkip, TOKEN_BASED_AUTH_ENTRY_POINT);
JwtTokenAuthenticationProcessingFilter filter
= new JwtTokenAuthenticationProcessingFilter(failureHandler, tokenExtractor, matcher);
filter.setAuthenticationManager(this.authenticationManager);
return filter;
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(ajaxAuthenticationProvider);
auth.authenticationProvider(jwtAuthenticationProvider);
}
@Bean
protected BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // We don't need CSRF for JWT based authentication
.exceptionHandling()
.authenticationEntryPoint(this.authenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(FORM_BASED_LOGIN_ENTRY_POINT).permitAll() // Login end-point
.antMatchers(TOKEN_REFRESH_ENTRY_POINT).permitAll() // Token refresh end-point
.antMatchers("/console").permitAll() // H2 Console Dash-board - only for testing
.and()
.authorizeRequests()
.antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated() // Protected API End-points
.and()
.addFilterBefore(buildAjaxLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
@配置
@启用Web安全性
公共类WebSecurityConfig扩展了WebSecurityConfigureAdapter{
公共静态最终字符串JWT_TOKEN_HEADER_PARAM=“X-Authorization”;
公共静态最终字符串形式基于登录登录条目点=“/api/auth/LOGIN”;
公共静态最终字符串标记基于身份验证入口点=“/api/**”;
公共静态最终字符串标记\u刷新\u条目\u点=“/api/auth/TOKEN”;
受保护的JwtTokenAuthenticationProcessingFilter buildJwtTokenAuthenticationProcessingFilter()引发异常{
List pathsToSkip=Arrays.asList(令牌\刷新\条目\点,基于表单\登录\条目\点);
SkipPathRequestMatcher matcher=新的SkipPathRequestMatcher(路径跳过,基于令牌的认证入口点);
JwtTokenAuthenticationProcessingFilter过滤器
=新的JwtTokenAuthenticationProcessingFilter(failureHandler、tokenExtractor、matcher);
filter.setAuthenticationManager(this.authenticationManager);
回流过滤器;
}
@豆子
@凌驾
公共AuthenticationManager authenticationManagerBean()引发异常{
返回super.authenticationManagerBean();
}
@凌驾
受保护的无效配置(AuthenticationManagerBuilder身份验证){
authenticationProvider(ajaxAuthenticationProvider);
authenticationProvider(jwtAuthenticationProvider);
}
@豆子
受保护的BCryptPasswordEncoder passwordEncoder(){
返回新的BCryptPasswordEncoder();
}
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
http
.csrf().disable()//基于JWT的身份验证不需要csrf
.例外处理()
.authenticationEntryPoint(此.authenticationEntryPoint)
.及()
.会议管理()
.sessionCreationPolicy(sessionCreationPolicy.STATELESS)
.及()
.授权请求()
.antMatchers(基于表单的登录入口点)。permitAll()//登录终点
.antMatchers(令牌\刷新\入口\点).permitAll()//令牌刷新端点
.antMatchers(“/console”).permitAll()//H2控制台仪表板-仅用于测试
.及()
.授权请求()
.antMatchers(基于令牌的认证入口点)。authenticated()//受保护的API端点
.及()
.addFilterBefore(buildAjaxLoginProcessingFilter(),UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(),UsernamePasswordAuthenticationFilter.class);
}
}
web.ignering()。antMatchers(“/v1/pricing/login”)是否应跳过此url的筛选器?这不是web.ignoring()的目的吗?可能是重复的