mtn*_*tnp 1 java security authentication spring spring-security
我的自定义过滤器基于UsernamePasswordAuthenticationFilter
需求,AuthenticationManager
但每次我调用该方法时,attemptAuthentication()
编译都会失败:
Authentication auth2 = this.getAuthenticationManager().authenticate(authRequest);
Run Code Online (Sandbox Code Playgroud)
为AuthenticationManager
空:
java.lang.NullPointerException: null
at app.shellx.security.CustomUsernamePasswordAuthenticationFilter.attemptAuthentication(CustomUsernamePasswordAuthenticationFilter.java:75) ~[classes/:na]
Run Code Online (Sandbox Code Playgroud)
网络安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Autowired
private JwtTokenFilter jwtTokenFilter;
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.cors().and()
.csrf().disable()
.authorizeRequests() // .antMatchers("/**")
.antMatchers("/login/**", "/register/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
//.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
.addFilterAt(new CustomUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.formLogin()
.loginPage("http://localhost:4200/login")//.failureUrl("/login-error")
.loginProcessingUrl("/login")
.usernameParameter("email")
.successHandler(customAuthenticationSuccessHandler)
.and()
.logout()
.permitAll();
}
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider()); // AuthenticationProvider inserted into ProviderManager
}
@Bean
public CustomDaoAuthenticationProvider authenticationProvider() {
CustomDaoAuthenticationProvider authenticationProvider = new CustomDaoAuthenticationProvider();
authenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());
authenticationProvider.setUserDetailsService(userService);
return authenticationProvider;
}
/*@Bean
public CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter() throws Exception {
return new CustomUsernamePasswordAuthenticationFilter(authenticationManager());
}*/
//@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
// Return the AuthenticationManager used by the configure(AuthenticationManagerBuilder auth) method
@Bean(name = "CustomAuthenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
System.out.println("Configuration of authenticationManagerBean");
return super.authenticationManagerBean();
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebConfig() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(
"http://localhost:4200")
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS")
.allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method",
"Access-Control-Request-Headers", "Authorization", "Cache-Control",
"Access-Control-Allow-Origin")
.exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")
.allowCredentials(true).maxAge(3600);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
自定义过滤器
public class CustomUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private boolean postOnly = true;
public CustomUsernamePasswordAuthenticationFilter() { // AuthenticationManager authenticationManager
super(new AntPathRequestMatcher("/login", "POST"));
//this.setAuthenticationManager(authenticationManager);
System.out.println("Constructor filter");
}
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
UsernamePasswordAuthenticationToken authRequest = null;
try {
authRequest = this.getUserNamePasswordAuthenticationToken(request);
} catch (IOException e) {
e.printStackTrace();
}
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
System.out.println("AVANT AUTHENTIFICATION : "+authRequest.getPrincipal() + " " + authRequest.getCredentials());
//this.setAuthenticationManager(authenticationManager);
Authentication auth2 = this.getAuthenticationManager().authenticate(authRequest);
System.out.println("APRES AUTHENTIFICATION : "+auth2.getPrincipal() + " " + auth2.getCredentials());
return auth2;
}
private UsernamePasswordAuthenticationToken getUserNamePasswordAuthenticationToken(HttpServletRequest request) throws IOException {
StringBuffer sb = new StringBuffer();
BufferedReader bufferedReader = null;
String content = "";
AuthReq sr = null;
try {
bufferedReader = request.getReader();
char[] charBuffer = new char[128];
int bytesRead;
while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) {
sb.append(charBuffer, 0, bytesRead);
}
content = sb.toString();
ObjectMapper objectMapper = new ObjectMapper();
try{
sr = objectMapper.readValue(content, AuthReq.class);
}catch(Throwable t){
throw new IOException(t.getMessage(), t);
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
System.out.println("email : "+sr.getEmail());
System.out.println("password : "+sr.getPassword());
return new UsernamePasswordAuthenticationToken(sr.getEmail(), sr.getPassword());
}
public static class AuthReq {
String email;
String password;
public String getEmail() {
return email;
}
public String getPassword() {
return password;
}
}
@Autowired
@Qualifier("CustomAuthenticationManager")
@Override
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
System.out.println("Setter custom filter");
super.setAuthenticationManager(authenticationManager);
}
Run Code Online (Sandbox Code Playgroud)
我尝试了几种解决方案,例如:
如何在自定义过滤器中使用 Java 配置注入 AuthenticationManager
无法通过 @Autowired 将 AuthenticationManager 传递给自定义过滤器
Spring boot安全配置 - 必须指定authenticationManager
AuthenticationManager
我最终选择了第一个,因为我认为为项目提供一个 bean 比CustomFilter
只使用一次的 bean更有用。
顺便问一下,对于您来说,实现这样的过滤器的最佳解决方案是什么(避免循环依赖、更好的维护……)?
您的CustomUsernamePasswordAuthenticationFilter
过滤器不受 Spring 管理(因为您直接创建了它),因此过滤器中没有 Spring 管理的依赖注入行为。这就是为什么AuthenticationManager
从未注入并且现在为空的原因。
假设你暴露你的AuthenticationManager
豆子......
您可以通过您的过滤器中的方法使您的过滤器成为一个bean(注意Spring Boot中bean的自动注册Filter
)@Bean
WebSecurityConfig
或者,您可以在创建过滤器对象时简单地将 传递给AuthenticationManager
过滤器(通过其构造函数或设置器)。没有必要将过滤器暴露为 bean。
归档时间: |
|
查看次数: |
2637 次 |
最近记录: |