访问被拒绝,在使用Spring Boot安全性JWT更改密码后。

huangapple go评论92阅读模式
英文:

Access denied after changed password with spring boot security JWT

问题

以下是要翻译的内容:

我正在为我的应用程序实现Spring Boot安全性。登录功能正常工作,但是不知何故,每当我测试更改密码功能时,它总是失败。我在数据库中检查了密码已经更新为新的HashString,但我无法使用旧密码和新密码登录。请帮忙!

这是更改密码的API:

  1. @PutMapping("/reset-password")
  2. public ResponseEntity resetPassword(@RequestBody String password) {
  3. // 提取用户名
  4. String username = SecurityContextHolder.getContext().getAuthentication()
  5. .getPrincipal().toString();
  6. ApplicationUser applicationUser = applicationUserRepo.findByUsername(username);
  7. if (applicationUser == null) {
  8. return ResponseEntity.badRequest().body("找不到用户名");
  9. }
  10. applicationUser.setPassword(bCryptPasswordEncoder.encode(password));
  11. applicationUserRepo.save(applicationUser);
  12. Logs log = new Logs(TimeConverter.getVietnamCurrentTime(), "PASSWORD", "User", applicationUser.getUsername(), applicationUser.getUsername());
  13. logsRepo.save(log);
  14. return ResponseEntity.ok().body("密码已成功更改!");
  15. }

这是我的WebSecurityConfigurerAdapter的实现:

  1. @EnableWebSecurity
  2. @Configuration
  3. public class WebSecurity extends WebSecurityConfigurerAdapter {
  4. private UserDetailsServiceImpl userDetailsService;
  5. @Autowired
  6. private BCryptPasswordEncoder bCryptPasswordEncoder;
  7. public WebSecurity(UserDetailsServiceImpl userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
  8. this.userDetailsService = userDetailsService;
  9. this.bCryptPasswordEncoder = bCryptPasswordEncoder;
  10. }
  11. @Override
  12. protected void configure(HttpSecurity http) throws Exception {
  13. http.cors().and().csrf().disable().authorizeRequests()
  14. .antMatchers(HttpMethod.POST, LOGIN_URL).permitAll()
  15. //.antMatchers("/login").permitAll()
  16. .anyRequest().authenticated()
  17. .and()
  18. .addFilter(new JWTAuthenticationFilter(authenticationManager()))
  19. .addFilter(new JWTAuthorizationFilter(authenticationManager()))
  20. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  21. }
  22. @Bean
  23. public AuthenticationFailureHandler authenticationFailureHandler() {
  24. return new CustomAuthenticationFailureHandler();
  25. }
  26. @Override
  27. public void configure(AuthenticationManagerBuilder auth) throws Exception {
  28. auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
  29. }
  30. @Bean
  31. public CorsConfigurationSource corsConfigurationSource() {
  32. final CorsConfiguration configuration = new CorsConfiguration();
  33. configuration.setAllowedOrigins(ImmutableList.of("*"));
  34. configuration.setAllowedMethods(ImmutableList.of("HEAD",
  35. "GET", "POST", "PUT", "DELETE", "PATCH"));
  36. configuration.setAllowCredentials(true);
  37. configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
  38. final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  39. source.registerCorsConfiguration("/**", configuration);
  40. return source;
  41. }
  42. @Override
  43. @Bean
  44. public AuthenticationManager authenticationManagerBean() throws Exception {
  45. return super.authenticationManagerBean();
  46. }
  47. }

AuthenticationFilter:

  1. public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
  2. private AuthenticationManager authenticationManager;
  3. public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
  4. this.authenticationManager = authenticationManager;
  5. }
  6. @Override
  7. public Authentication attemptAuthentication(HttpServletRequest req,
  8. HttpServletResponse res) throws AuthenticationException {
  9. try {
  10. ApplicationUser creds = new ObjectMapper()
  11. .readValue(req.getInputStream(), ApplicationUser.class);
  12. return authenticationManager.authenticate(
  13. new UsernamePasswordAuthenticationToken(
  14. creds.getUsername(),
  15. creds.getPassword(),
  16. new ArrayList<>())
  17. );
  18. } catch (IOException e) {
  19. System.out.println("出错了");
  20. throw new RuntimeException(e);
  21. }
  22. }
  23. @Override
  24. protected void successfulAuthentication(HttpServletRequest req,
  25. HttpServletResponse res,
  26. FilterChain chain,
  27. Authentication auth) {
  28. String token = JWT.create()
  29. .withSubject(((User) auth.getPrincipal()).getUsername())
  30. .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
  31. .sign(HMAC512(SECRET.getBytes()));
  32. res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
  33. res.addHeader("Access-Control-Expose-Headers","*");
  34. }
  35. @Override
  36. protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
  37. throws IOException, ServletException {
  38. response.getWriter().write("出错了");
  39. super.unsuccessfulAuthentication(request, response, failed);
  40. }
  41. }
英文:

I'm implementing spring boot security for my application. The login function works fine, but somehow whenever I test the change-password function, it's always failed, I checked in the database the password has been updated with the new HashString, but I cannot login with both old-password and new-password. Please help !

Here is the change-password API

  1. @PutMapping(&quot;/reset-password&quot;)
  2. public ResponseEntity resetPassword(@RequestBody String password){
  3. //extract user name
  4. String username = SecurityContextHolder.getContext().getAuthentication()
  5. .getPrincipal().toString();
  6. ApplicationUser applicationUser = applicationUserRepo.findByUsername(username);
  7. if(applicationUser == null ){
  8. return ResponseEntity.badRequest().body(&quot;Could not find UserName&quot;);
  9. }
  10. applicationUser.setPassword(bCryptPasswordEncoder.encode(password));
  11. applicationUserRepo.save(applicationUser);
  12. Logs log = new Logs (TimeConverter.getVietnamCurrentTime(),&quot;PASSWORD&quot;, &quot;User&quot;, applicationUser.getUsername(), applicationUser.getUsername() );
  13. logsRepo.save(log);
  14. return ResponseEntity.ok().body(&quot;Password changed successfully!&quot;);
  15. }

Here is my implementation of WebSecurityConfigurerAdapter

  1. @EnableWebSecurity
  2. @Configuration
  3. public class WebSecurity extends WebSecurityConfigurerAdapter {
  4. private UserDetailsServiceImpl userDetailsService;
  5. @Autowired
  6. private BCryptPasswordEncoder bCryptPasswordEncoder;
  7. public WebSecurity(UserDetailsServiceImpl userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
  8. this.userDetailsService = userDetailsService;
  9. this.bCryptPasswordEncoder = bCryptPasswordEncoder;
  10. }
  11. @Override
  12. protected void configure(HttpSecurity http) throws Exception {
  13. http.cors().and().csrf().disable().authorizeRequests()
  14. .antMatchers(HttpMethod.POST, LOGIN_URL).permitAll()
  15. //.antMatchers(&quot;/login&quot;).permitAll()
  16. .anyRequest().authenticated()
  17. .and()
  18. .addFilter(new JWTAuthenticationFilter(authenticationManager()))
  19. .addFilter(new JWTAuthorizationFilter(authenticationManager()))
  20. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  21. }
  22. @Bean
  23. public AuthenticationFailureHandler authenticationFailureHandler() {
  24. return new CustomAuthenticationFailureHandler();
  25. }
  26. @Override
  27. public void configure(AuthenticationManagerBuilder auth) throws Exception {
  28. auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
  29. }
  30. @Bean
  31. public CorsConfigurationSource corsConfigurationSource() {
  32. final CorsConfiguration configuration = new CorsConfiguration();
  33. configuration.setAllowedOrigins(ImmutableList.of(&quot;*&quot;));
  34. configuration.setAllowedMethods(ImmutableList.of(&quot;HEAD&quot;,
  35. &quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;, &quot;DELETE&quot;, &quot;PATCH&quot;));
  36. configuration.setAllowCredentials(true);
  37. configuration.setAllowedHeaders(ImmutableList.of(&quot;Authorization&quot;, &quot;Cache-Control&quot;, &quot;Content-Type&quot;));
  38. final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  39. source.registerCorsConfiguration(&quot;/**&quot;, configuration);
  40. return source;
  41. }
  42. @Override
  43. @Bean
  44. public AuthenticationManager authenticationManagerBean() throws Exception {
  45. return super.authenticationManagerBean();
  46. }
  47. }

AuthenticationFilter

  1. public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
  2. private AuthenticationManager authenticationManager;
  3. public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
  4. this.authenticationManager = authenticationManager;
  5. }
  6. @Override
  7. public Authentication attemptAuthentication(HttpServletRequest req,
  8. HttpServletResponse res) throws AuthenticationException {
  9. try {
  10. ApplicationUser creds = new ObjectMapper()
  11. .readValue(req.getInputStream(), ApplicationUser.class);
  12. return authenticationManager.authenticate(
  13. new UsernamePasswordAuthenticationToken(
  14. creds.getUsername(),
  15. creds.getPassword(),
  16. new ArrayList&lt;&gt;())
  17. );
  18. } catch (IOException e) {
  19. System.out.println(&quot;fucked&quot;);
  20. throw new RuntimeException(e);
  21. }
  22. }
  23. @Override
  24. protected void successfulAuthentication(HttpServletRequest req,
  25. HttpServletResponse res,
  26. FilterChain chain,
  27. Authentication auth) {
  28. String token = JWT.create()
  29. .withSubject(((User) auth.getPrincipal()).getUsername())
  30. .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
  31. .sign(HMAC512(SECRET.getBytes()));
  32. res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
  33. res.addHeader(&quot;Access-Control-Expose-Headers&quot;,&quot;*&quot;);
  34. }
  35. @Override
  36. protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
  37. throws IOException, ServletException {
  38. response.getWriter().write(&quot;blalfaf&quot;);
  39. super.unsuccessfulAuthentication(request, response, failed);
  40. }
  41. }

答案1

得分: 1

尝试使用:

  1. addFilterBefore(new JWTAuthenticationFilter(authenticationManager(), UsernamePasswordAuthenticationFilter.class)

而不是仅仅使用:

  1. addFilter(....

在你的 WebSecurity.configure(..... 中。这将会把你自己的过滤器放在原始的 UsernamePasswordAuthenticationFilter 之前。也许你的过滤器是排在最后的,导致登录在它之前失败。

英文:

Try using:

  1. addFilterBefore(new JWTAuthenticationFilter(authenticationManager(), UsernamePasswordAuthenticationFilter.class)

instead of just

  1. addFilter(....

in your WebSecurity.configure(.....

This will put your own filter before the original UsernamePasswordAuthenticationFilter. Maybe your filter is last in line and the login is failing before.

huangapple
  • 本文由 发表于 2020年10月6日 19:12:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/64224625.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定