我正在编写一个程序,它使用了带有Spring Security的JWT身份验证。我已经实现了自定义授权和身份验证过滤器。另外,我需要持久化我的令牌,它是由这些过滤器形成的。为此,我创建了令牌DAO服务,它自动连接到过滤器,并用@component
注释标记我的过滤器以自动连接该服务。但我无法正确自动执行身份验证管理器。
我尝试在安全配置类中公开身份验证管理器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();
}
}
@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
通过将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组件。
我在Project中使用了Spring Boot和JWT以及Spring security。Spring Boot:2.3.5.发布JJWT Verison:0.11.2 我想要以下异常响应,这是我的自定义响应类:
我有Springmvc应用程序。我添加了带有CustomAuthentiationManager的Spring Security。这是appC中包含的application-security.xmlontex.xml.login.jsp我使用带有2个输入的标准登录页面:name='j_username'
我在后端的一个spring引导应用程序中工作,我想使用firebase来进行身份验证过程。我在我的spring启动项目中正确地设置了firebase,并在以下开源存储库中添加了安全层:https://github.com/savicprvoslav/spring-boot-starter 因为Firebase令牌的生存期为1小时,所以当Firebase SDK抛出FireBaseAuthExcep
注意:我的问题与Spring-Boot REST API+web应用程序的安全性有关。
我想添加用户的ID作为自定义声明到我的令牌。 但我无法在过滤器中获取用户id,因为依赖注入在过滤器中不起作用。我尝试使用UserService的构造函数,但在这个服务中,我有一个存储库,它是im@Autowiring,所以在调试模式下,我看到userRepository字段为空。 我的问题是我将如何添加这个自定义声明?也许这是添加这个的另一种方式。 我正在学习本教程(没有“旁白”章节)https: