我正在编写一个使用JWT身份验证和Spring Security的程序。我已经实现了自定义的授权和身份验证过滤器。另外,我需要保留由这些过滤器形成的令牌。为此,我创建了令牌DAO服务,该服务自动连接到过滤器,并用@Component
批注标记“我的过滤器”以自动连接该服务。但是我无法正确地自动连接身份验证管理器。
我曾尝试在Security Configuration类Authentication Manager bean中公开,但没有结果。
这是我的安全配置类:
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
@ComponentScan(value = "ua.edu.viti.medex")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
UsersDetailsService usersDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(usersDetailsService).passwordEncoder(encoder());
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/signup").hasRole("ADMIN")
.antMatchers("/login").permitAll()
.antMatchers("/signout").permitAll()
.antMatchers("/**").authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManagerBean()))
.addFilter(new JwtAuthorizationFilter(authenticationManagerBean()))
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
这是我的JwtAuthenticationFilter
@Component
@SuppressWarnings({"WeakerAccess", "SpringJavaAutowiredMembersInspection"})
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Autowired
TokenServiceImpl tokenService;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
setAuthenticationManager(authenticationManager);
setFilterProcessesUrl(SecurityConstants.AUTH_LOGIN_URL);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
String body = "";
if ("POST".equalsIgnoreCase(request.getMethod()))
{
try {
body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
} catch (IOException e) {
e.printStackTrace();
}
}
GsonJsonParser jsonParser = new GsonJsonParser();
Map<String, Object> data = jsonParser.parseMap(body);
Map<String, Object> credentials = jsonParser.parseMap((String) data.get("data"));
String username = (String) (credentials != null ? credentials.get("username") : null);
String password = (String) (credentials != null ? credentials.get("password") : null);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
return authenticationManager.authenticate(authenticationToken);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain, Authentication authentication) throws IOException {
User user = ((User) authentication.getPrincipal());
Tokens token = null;
try{
token = tokenService.getTokenFromEmail(user.getUsername());
} catch (NotFoundException e) {
List<String> roles = user.getAuthorities()
.stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList());
byte[] signingKey = SecurityConstants.JWT_SECRET.getBytes();
String newToken = Jwts.builder()
.signWith(Keys.hmacShaKeyFor(signingKey), SignatureAlgorithm.HS512)
.setHeaderParam("typ", SecurityConstants.TOKEN_TYPE)
.setIssuer(SecurityConstants.TOKEN_ISSUER)
.setAudience(SecurityConstants.TOKEN_AUDIENCE)
.setSubject(user.getUsername())
.setExpiration(new Date(System.currentTimeMillis() + 7200000))
.claim("role", roles)
.compact();
String completeToken = SecurityConstants.TOKEN_PREFIX + newToken;
tokenService.addTokenData(completeToken);
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
out.print(completeToken);
out.flush();
response.addHeader(SecurityConstants.TOKEN_HEADER, SecurityConstants.TOKEN_PREFIX + newToken);
return;
}
if(token.isValid() && (System.currentTimeMillis() - token.getExpiration().getTime() > 900000)){
String completeToken = token.getToken();
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
out.print(completeToken);
out.flush();
response.addHeader(SecurityConstants.TOKEN_HEADER, completeToken);
return;
}else {
String completeToken = null;
try {
completeToken = tokenService.refreshToken(token).getToken();
} catch (NotFoundException e) {
e.printStackTrace();
}
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
out.print(completeToken);
out.flush();
response.addHeader(SecurityConstants.TOKEN_HEADER, completeToken);
}
}
}
我在尝试构建项目时遇到的错误。
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jwtAuthenticationFilter' defined in file [D:\Master\MedEx\AuthModule\target\classes\ua\edu\viti\medex\auth\config\secutiry\JwtAuthenticationFilter.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: authenticationManager must be specified
答案 0 :(得分:0)
addind DAO类作为构造函数参数解决了问题。
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager(), tokenDAO))
.addFilter(new JwtAuthorizationFilter(authenticationManager(), tokenDAO))
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
@Autowired
TokenDAOImpl tokenDAO;
然后就没有必要将过滤器用作Spring Component。