我的问题是-可能我的依赖项定义错误,但是找不到错误!
┌─────┐
| jwtAuthorizationTokenFilter defined in file [\JwtAuthorizationTokenFilter.class]
↑ ↓
| jwtUserDetailsService (security.service.JwtUserDetailsService.authenticationManager)
↑ ↓
| webSecurityConfig (security.WebSecurityConfig.authenticationTokenFilter)
└─────┘
JwtAuthorizationTokenFilter.class
@Component
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final UserDetailsService userDetailsService;
private final JwtTokenUtil jwtTokenUtil;
private final String tokenHeader;
public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, @Value("${jwt.header}") String tokenHeader) {
this.userDetailsService = userDetailsService;
this.jwtTokenUtil = jwtTokenUtil;
this.tokenHeader = tokenHeader;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
logger.debug("processing authentication for '{}'", request.getRequestURL());
System.out.println("JwtAuthorTokenFilter Header request " + request.getHeader(this.tokenHeader));
final String requestHeader = request.getHeader(this.tokenHeader);
String username = null;
String authToken = null;
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
authToken = requestHeader.substring(7);
System.out.println("Auth token " + authToken);
try {
username = jwtTokenUtil.getUsernameFromToken(authToken);
} catch (IllegalArgumentException e) {
logger.error("an error occurred during getting username from token", e);
} catch (ExpiredJwtException e) {
logger.warn("the token is expired and not valid anymore", e);
}
} else {
logger.warn("couldn't find bearer string, will ignore the header");
}
logger.debug("checking authentication for user '{}'", username);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
logger.debug("security context was null, so authorizing user");
UserDetails userDetails;
try {
userDetails = userDetailsService.loadUserByUsername(username);
} catch (UsernameNotFoundException e) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
return;
}
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
logger.info("authorized user '{}', setting security context", username);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
}
JwtUserDetailsService
@Service("jwtUserDetailsService")
public class JwtUserDetailsService implements UserDetailsService {
@Autowired
private UserDAO userDAO;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDAO.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username));
} else {
return JwtUserFactory.create(user);
}
}
public void authenticate(String username, String password) {
Objects.requireNonNull(username);
Objects.requireNonNull(password);
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new AuthenticationException("User is disabled!", e);
} catch (BadCredentialsException e) {
throw new AuthenticationException("Bad credentials!", e);
}
}
}
WebSecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtUserDetailsService jwtUserDetailsService;
@Autowired
JwtAuthorizationTokenFilter authenticationTokenFilter;
@Value("${jwt.header}")
private String tokenHeader;
@Value("${jwt.route.authentication.path}")
private String authenticationPath;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(jwtUserDetailsService)
.passwordEncoder(passwordEncoderBean());
}
@Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated();
httpSecurity
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(
HttpMethod.POST,
authenticationPath
)
.and()
.ignoring()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js"
);
}
}
我尝试了所有事情:)删除了AuthenticationManager,重新配置了全局配置-但没有任何动作。也许我的Spring依赖知识不深,所以这就是我遇到这个常见问题的原因。
但是也许您知道如何解决该问题?
答案 0 :(得分:2)
代替过滤器上的@Component
,您可以尝试使用@Bean
在配置中创建它。从我的角度来看,您依赖于WebSecurityConfig
中声明的userDetailService,要构造它需要其AutoWired bean。
TL; DR,如果在JwtAuthorizationTokenFilter中使用@Autowired JwtAuthorizationTokenFilter authenticationTokenFilter;
@Autowired private JwtUserDetailsService jwtUserDetailsService
尝试:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtUserDetailsService jwtUserDetailsService;
@Value("${jwt.header}")
private String tokenHeader;
@Autowired
private JwtTokenUtil jwtTokenUtil
@Value("${jwt.route.authentication.path}")
private String authenticationPath;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(jwtUserDetailsService)
.passwordEncoder(passwordEncoderBean());
}
@Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated();
httpSecurity
.addFilterBefore(new JwtAuthorizationTokenFilter(jwtUserDetailsService, tokenUtil, tokenHeader), UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(
HttpMethod.POST,
authenticationPath
)
.and()
.ignoring()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js"
);
}
}
删除@Component:
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final UserDetailsService userDetailsService;
private final JwtTokenUtil jwtTokenUtil;
private final String tokenHeader;
public JwtAuthorizationTokenFilter(UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, @Value("${jwt.header}") String tokenHeader) {
this.userDetailsService = userDetailsService;
this.jwtTokenUtil = jwtTokenUtil;
this.tokenHeader = tokenHeader;
}
[.....]