问题描述
我有百里香的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.
您尚未为此适配器指定 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()
.antMatchers("/api/**") // apply JWTSecurityConfig to requests matching "/api/**"
.authorizeRequests()
.anyRequest().authenticated()
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
@Configuration
public class FormLoginConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.formLogin();
}
}
}
有关多个 WebSecurityConfigurerAdapter
的更多详细信息,请参阅多个 HttpSecurity
部分.
For more details on multiple WebSecurityConfigurerAdapter
, you can see the multiple HttpSecurity
section in the Spring Security reference docs.
有关 authorizeRequests()
和 requestMatchers()
之间的区别的更多详细信息,请参见此堆栈溢出问题.
For more details on the difference between authorizeRequests()
and requestMatchers()
, you can see this Stack Overflow question.
这篇关于多个WebSecurityConfigurerAdapters:Spring Security中的JWT身份验证和表单登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!