我有一个自定义UserDetailsService:
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private AccountRepository accountRepository;
@Autowired
private PasswordEncoder passwordEncoder;
private static Logger logger = LoggerFactory.getLogger(JWTLoginFilter.class);
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
CustomUserDetails account = accountRepository.findByUsername(username);
if (account != null) {
return account;
} else {
throw new UsernameNotFoundException("could not find the user '" + username + "'");
}
}
public void saveUser(String userName, String password) {
CustomUserDetails userDetails = new CustomUserDetails(userName, passwordEncoder.encode(password), true, true, true,true, AuthorityUtils.commaSeparatedStringToAuthorityList("USER_ROLE"));
accountRepository.save(userDetails);
logger.debug("New user with username " + userName + " was created");
}
}
并且我有一个注册过滤器(用于创建新用户)并扩展了
AbstractAuthenticationProcessingFilter
:public class JWTSignupFilter extends AbstractAuthenticationProcessingFilter {
@Autowired
private CustomUserDetailsService userDetailService;
private static Logger logger = LoggerFactory.getLogger(JWTLoginFilter.class);
public JWTSignupFilter(String url, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(url, HttpMethod.POST.toString()));
setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
CustomUserDetails creds = new ObjectMapper().readValue(request.getInputStream(), CustomUserDetails.class);
if (userDetailService.loadUserByUsername(creds.getUsername()) != null) {
logger.debug("Duplicate username " + creds.getUsername());
throw new AuthenticationException("Duplicate username") {
private static final long serialVersionUID = 1L;
};
}
userDetailService.saveUser(creds.getUsername(), creds.getPassword());
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(creds.getUsername(),creds.getPassword()));
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException, ServletException {
TokenAuthenticationService.addAuthentication(response, auth.getName());
chain.doFilter(request, response);
}
}
当执行达到
userDetailService.loadUserByUsername
时,我得到空指针异常,这意味着自动装配不起作用。我尝试像下面那样实现
ApplicationContextAware
,但是它仍然是Null
。我还用JWTSignupFilter
注释了@Service
,但它也不起作用。任何想法如何解决此问题?public class JWTSignupFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
private CustomUserDetailsService userDetailService;
.....
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
userDetailService = applicationContext.getBean(CustomUserDetailsService.class);
}
}
这是
configure
中覆盖的WebSecurityConfigurerAdapter
方法,其中登录过滤器进入播放状态:@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout().logoutUrl("/logout").logoutSuccessHandler(logoutHandler).logoutSuccessUrl("/login").invalidateHttpSession(true)
.and()
// We filter the api/signup requests
.addFilterBefore(
new JWTSignupFilter("/signup", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// We filter the api/login requests
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in
// header
.addFilterBefore(
new JWTAuthenticationFilter(userDetailsServiceBean()),
UsernamePasswordAuthenticationFilter.class);
}
最佳答案
尝试这个:
将以下代码添加到您的配置文件中:
@Bean
public JWTSignupFilter jWTSignupFilter() throws Exception {
return new JWTSignupFilter("/login", authenticationManager());
}
将以下行添加到您的
WebSecurityConfigurerAdapter
扩展类中@Autowired
JWTLoginFilter jWTSignupFilter
并更换
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
与
.addFilterBefore(
jWTSignupFilter,
UsernamePasswordAuthenticationFilter.class)
更新
您的WebSecurityConfigurerAdapter扩展类应如下所示:
public Class CustomConfigurationClass extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
.and()
.authorizeRequests()
.antMatchers("/signup").permitAll()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout().logoutUrl("/logout").logoutSuccessHandler(logoutHandler).logoutSuccessUrl("/login").invalidateHttpSession(true)
.and()
// We filter the api/signup requests
.addFilterBefore(
jWTSignupFilter(),
UsernamePasswordAuthenticationFilter.class)
// We filter the api/login requests
.addFilterBefore(
new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in
// header
.addFilterBefore(
new JWTAuthenticationFilter(userDetailsServiceBean()),
UsernamePasswordAuthenticationFilter.class);
}
@Bean
public JWTSignupFilter jWTSignupFilter() throws Exception {
return new JWTSignupFilter("/signup", authenticationManager());
}
}