Java 在springboot中实现JWT令牌
我已经实现了一个在spring boot中使用JWT令牌进行身份验证的解决方案,除了两件事之外,它在重定向到登录页面之前不会重定向到发出请求的页面,SuccessHandler也不起作用。从我所做的测试来看,问题似乎是因为没有成功的身份验证,但我不知道如何解决它。代码如下 证券配置Java 在springboot中实现JWT令牌,java,spring,spring-boot,spring-security,jwt,Java,Spring,Spring Boot,Spring Security,Jwt,我已经实现了一个在spring boot中使用JWT令牌进行身份验证的解决方案,除了两件事之外,它在重定向到登录页面之前不会重定向到发出请求的页面,SuccessHandler也不起作用。从我所做的测试来看,问题似乎是因为没有成功的身份验证,但我不知道如何解决它。代码如下 证券配置 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapt
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
JwtTokenProvider jwtTokenProvider;
@Autowired
CustomAuthenticationSuccessHandler authenticationSuccess;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
UserDetailsService userDetailsService = mongoUserDetails();
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests()
.antMatchers("/", "/search_posts", "/wall/**", "/resources/**", "/css/**", "/js/**", "/webjars/**", "/api/auth/login").permitAll()
.antMatchers("/exams/**").hasAuthority(Role.STUDENT.toString())
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll()
.successHandler(authenticationSuccess)
.and().csrf().disable();
// Apply JWT
http.apply(new JwtConfigurer(jwtTokenProvider));
//filtro para poner JWT en la cabecera del request
http.addFilterBefore(new RequestWrapperFilter(), UsernamePasswordAuthenticationFilter.class);
//http.addFilterBefore(new JWTAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
http.httpBasic().disable();
//.apply(new JwtConfigurer(jwtTokenProvider));
}//.and()//.exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint())
@Bean
public PasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public AuthenticationEntryPoint unauthorizedEntryPoint() {
return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Unauthorized");
}
@Bean
public UserDetailsService mongoUserDetails() {
return new CustomUserDetailsService();
}
}
jwttoken过滤器
public class JwtTokenFilter extends GenericFilterBean {
private JwtTokenProvider jwtTokenProvider;
public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
throws IOException, ServletException {
String token = jwtTokenProvider.resolveToken((HttpServletRequest) req);
if (token != null && jwtTokenProvider.validateToken(token)) {
Authentication auth = token != null ? jwtTokenProvider.getAuthentication(token) : null;
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);
}
filterChain.doFilter(req, res);
}
}
jwttoken提供程序
@Component
public class JwtTokenProvider {
@Value("${security.jwt.token.secret-key:secret}")
private String secretKey = Constants.SECRET;
@Value("${security.jwt.token.expire-length:3600000}")
private long validityInMilliseconds = 10800000; // 3h
@Autowired
private CustomUserDetailsService userDetailsService;
@PostConstruct
protected void init() {
secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
}
public String createToken(String username, Set<Role> roles) {
Claims claims = Jwts.claims().setSubject(username);
claims.put("roles", roles);
Date now = new Date();
Date validity = new Date(now.getTime() + validityInMilliseconds);
return Jwts.builder()//
.setClaims(claims)//
.setIssuedAt(now)//
.setExpiration(validity)//
.signWith(SignatureAlgorithm.HS256, secretKey)//
.compact();
}
public Authentication getAuthentication(String token) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(getUsername(token));
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}
public String getUsername(String token) {
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
}
public String resolveToken(HttpServletRequest req) {
String bearerToken = req.getHeader(Constants.AUTHORIZATION);
if (bearerToken != null && bearerToken.startsWith(Constants.BEARER)) {
return bearerToken.substring(Constants.BEARER.length(), bearerToken.length());
}
return null;
}
public boolean validateToken(String token) {
try {
Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
if (claims.getBody().getExpiration().before(new Date())) {
return false;
}
return true;
} catch (JwtException | IllegalArgumentException e) {
throw new JwtException("Expired or invalid JWT token");
}
}
}
拜托,我有点迷路了,我找不到问题的解决方案,spring在登录页面之前将您重定向到请求页面是真的吗?有没有办法在登录前重定向到上一页?谢谢您如何发送身份验证信息?用户名/密码是否作为json发送?
public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private JwtTokenProvider jwtTokenProvider;
public JwtConfigurer(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public void configure(HttpSecurity http) throws Exception {
JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
JwtTokenProvider jwtTokenProvider;
@Autowired
UserRepository users;
@Autowired
private CustomUserDetailsService userService;
@Autowired
AuthenticationSuccessHandler ash;
@PostMapping("/login")
public void login(@ModelAttribute("user") Users user, HttpServletRequest req, HttpServletResponse response) throws IOException, ServletException {
try {
//set authentication
Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);
//create a token
String token = jwtTokenProvider.createToken(user.getUsername(), this.users.findByUsername(user.getUsername()).getRoles());
//create and set a cookie
Cookie cookie = new Cookie(Constants.TOKEN, token);
cookie.setMaxAge(3 * 60 * 60); // expires in 3 hours
cookie.setHttpOnly(true);
cookie.setPath("/");
//add cookie to response
response.addCookie(cookie);
//call to onauthenticationsuccess
//ash.onAuthenticationSuccess(req, response, auth);
}
catch (AuthenticationException e) {
throw new BadCredentialsException("Invalid email/password supplied");
}
}