问题描述
我有带有 thymeleaf 的 spring boot 应用程序.我正在使用 spring security formLogin 方法来保证安全,现在我只需要为一些 API 添加 JWT.
I have spring boot app with thymeleaf. I am using spring security formLogin method for security and now I need to add JWT for only some APIs.
@EnableWebSecurity
public class SecurityConfigurations {
@Autowired
UserDetailsServiceImpl userDetails;
@Bean
DaoAuthenticationProvider provider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(encoder());
provider.setUserDetailsService(userDetails);
return provider;
}
@Bean
PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Configuration
@Order(1)
public class JWTSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
DaoAuthenticationProvider provider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(provider);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/api/user/authenticate").permitAll()
.antMatchers("/api/user/**").hasRole("USER")
.and().
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Add a filter to validate the tokens with every request
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
@Configuration
public static class FormLoginConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
DaoAuthenticationProvider provider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(provider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin/admins**").hasAnyRole("SADMIN").antMatchers("/admin/**")
.hasAnyRole("ADMIN", "SADMIN", "WADMIN").antMatchers("/rest/**")
.hasAnyRole("ADMIN", "SADMIN", "WADMIN", "USER").antMatchers("/user/**").hasAnyRole("USER")
.anyRequest().permitAll().and().formLogin().loginPage("/sign-in-up")
.loginProcessingUrl("/signInProcess").usernameParameter("phone").and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/")
.invalidateHttpSession(false).and().csrf().disable().cors();
}
}
}
通过执行此操作,JWT 可以正常工作,但 formlogin 已停止并调用/signInProcess".现在给404:
by doing this JWT is working fine as just I need but the formlogin has stopped and calling "/signInProcess" now give 404:
注意:如果我更改顺序并设置 formLogin @order(1) 它会再次工作,但当然不会工作.
NOTE: if I change the order and make formLogin @order(1) it works again but of course will not work.
我也尝试像这样将它们结合起来,现在它们都可以正常工作,但是如果 JWT 身份验证错误将返回 formlogin thymeleaf 错误页面,则会出现异常处理问题:
Also I tried to combine them both like this now it is both works fine but the problem with exception handling if the JWT authentication error will return formlogin thymeleaf error page :
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin/admins**").hasAnyRole("SADMIN").antMatchers("/admin/**")
.hasAnyRole("ADMIN", "SADMIN", "WADMIN").antMatchers("/rest/**")
.hasAnyRole("ADMIN", "SADMIN", "WADMIN", "USER").antMatchers("/user/**").hasAnyRole("USER")
.antMatchers("/api/user/authenticate").permitAll()
.antMatchers("/api/user/**").hasRole("USER")
.anyRequest().permitAll().and().formLogin().loginPage("/sign-in-up")
.loginProcessingUrl("/signInProcess").usernameParameter("phone").and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/")
.invalidateHttpSession(false).and().csrf().disable().cors();
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
任何建议使这项工作.谢谢.
any suggestions to make this work. thank you.
推荐答案
您的 WebSecurityConfigurerAdapters
将按顺序处理传入的请求.
由于 JWTSecurityConfig
带有 @Order(1)
注释,它会首先处理请求.
Your WebSecurityConfigurerAdapters
will process the incoming requests in order.
Since JWTSecurityConfig
is annotated with @Order(1)
it will process the requests first.
你没有为这个Adapter指定一个antMatcher
,所以它会匹配所有的请求.
这意味着请求永远不会到达 FormLoginConfigurationAdapter
,因为 JWTSecurityConfig
匹配所有这些.
You have not specified a antMatcher
for this Adapter, so it will match all requests.
This means that a request will never reach FormLoginConfigurationAdapter
, since JWTSecurityConfig
matches them all.
如果您希望 JWTSecurityConfig
仅适用于某些请求,您可以在安全配置中指定 antMatcher
.
下面是一个例子:
If you want JWTSecurityConfig
to only apply to certain requests, you can specify an antMatcher
in your security configuration.
Below is an example:
@EnableWebSecurity
public class SecurityConfigurations {
@Configuration
@Order(1)
public class JWTSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers(matchers -> matchers
.antMatchers("/api/**") // apply JWTSecurityConfig to requests matching "/api/**"
)
.authorizeRequests(authz -> authz
.anyRequest().authenticated()
)
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
@Configuration
public class FormLoginConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authz -> authz
.anyRequest().authenticated()
)
.formLogin();
}
}
}
关于多个WebSecurityConfigurerAdapter
的更多细节,可以查看multiple HttpSecurity
部分.
For more details on multiple WebSecurityConfigurerAdapter
, you can see the multiple HttpSecurity
section in the Spring Security reference docs.
authorizeRequests()
和 requestMatchers()
的更多区别可以看这个 Stack Overflow 问题.
For more details on the difference between authorizeRequests()
and requestMatchers()
, you can see this Stack Overflow question.
这篇关于多个WebSecurityConfigurerAdapters:spring security中的JWT认证和表单登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!