当前位置:   article > 正文

关于Security oauth2 +Sso整合出现的问题_failed to authenticate since password does not mat

failed to authenticate since password does not match stored value

当搭建好security授权服务器,资源服务器,和单点登录客户端的时候,挺开心的,基本上都是使用注解写的,也没啥多大的变动.

但是在我使用ResponseBodyAdvice包装类统一返回响应请求的时候,问题就来了,再进行统一包装的时候也会将通过授权后返回的token信息进行包装,可是当客户端对返回的response进行解析的时候死活解析不出来,会把返回的信息全部放入到增强内容additionallnformation当中

这就令我很苦恼,也算没吃透security就开始写带来的问题,找了很多方法,但是都没啥意义.

主要我的客户端是使用security提供的默认的配置,都不好进行改动,而自己又不想去另写客户端(这样还要去写单点登录).

解决的方法其实也有

1.配置security中的响应请求进行重写,然后放入到security config配置中(写了,但由于是使用默认配置,报错了 bean冲突)

2.删掉统一包装方法(暂时使用,因为反正是授权,不包装也可以)

3.跟1其实差不多,别使用默认的注解配置,自己去配置客户端,写sso代码,这样就不用局限于默认框架的拘束之下了.

Security身份认证顺序问题

另一个问题,当用户被封禁后isEnabled()方法为false的时候,用户isAccountNonLocked()同时被触发时,这里就会提前返回用户账户被锁定,源码中首先校验的是是否锁定,在AbstractUserDetailsAuthenticationProvider类中有默认的校验方案

 这就会让用户接受到不正确的信息,而这正是默认实现的DaoAuthenticationProvider实现的校验策略,所以我们要用自己的AuthenticationProvider,并且去自己实现用户身份校验.

AuthenticationSuccessEvent无法监听问题

今天又遇到一个问题,监听类收不到广播类推送的登录成功消息,先放出代码.

  1. /**
  2. * 用户登录事件监听
  3. * 如果用户登录成功则在日志进行记录
  4. * 并且发送邮件告知用户登录,以及登录位置
  5. * 提醒end user账号被登录
  6. */
  7. @Component
  8. public class UserLoginListener {
  9. @Autowired
  10. private HttpServletRequest request;
  11. @Autowired
  12. private EmailUtil emailUtil;
  13. @EventListener(AuthenticationSuccessEvent.class)
  14. public void userLoginSuccessfulOnApplicationEvent(AuthenticationSuccessEvent event) throws MessagingException {
  15. //根据访问的请求ip查找用户的位置
  16. //http://whois.pconline.com.cn/?ip=123.91.217.123查询IP地址的地理位置
  17. String url = "http://whois.pconline.com.cn/?ip=" + this.getIpAddress();
  18. String result = this.getResult(url);
  19. int data = result.indexOf("位置:");
  20. int first = data + 3;
  21. int last = data + 20;
  22. String geographicLocation = result.substring(first, last).trim();
  23. System.out.println(geographicLocation);
  24. //拿到登录的用户信息
  25. Authentication authentication = event.getAuthentication();
  26. Object principal = authentication.getPrincipal();
  27. String userName = authentication.getName();
  28. String userEmail = null;
  29. //获取电子邮箱
  30. if (principal instanceof User) {
  31. User user = (User) principal;
  32. userEmail = user.getEmail();
  33. }
  34. String userRole = null;
  35. String bodyMessage = authentication.getName() + " 您好,您刚刚在 " + geographicLocation + "\n登录,如果这不是您" +
  36. "本人进行的操作,请赶紧修改密码或者冻结账号";
  37. Set<String> authorizeds = AuthorityUtils.authorityListToSet(authentication.getAuthorities());
  38. for (String authorized : authorizeds) {
  39. if (authorized.equals("normal")) {
  40. userRole = "尊敬的用户 ";
  41. break;
  42. } else if (authorized.equals("root")) {
  43. userRole = "超级管理员管理员SAMA ";
  44. } else if (authorized.equals("admin")) {
  45. userRole = "管理员SAMA ";
  46. } else if (authorized.equals("CLIENT")) {
  47. userRole = "Sso客户端信息 \n";
  48. bodyMessage = authentication.getName() + "--> 服务器启动了,Sso客户端正在上线中";
  49. }
  50. }
  51. //邮件的提示信息
  52. String emailMessage = userRole + bodyMessage;
  53. String email = userEmail;
  54. //发送邮件
  55. Thread thread = new Thread(() -> emailUtil.loginUpEmail(userName, emailMessage, email));
  56. thread.start();
  57. }

监听的是AuthenticationSuccessEvent这个类,这个类很有意思,它的推送是由ProviderManager验证成功后推送的,之前修改了AuthenticationProvider,也没出现什么问题,但是今天使用的时候就开始整活,死活都监听不到消息,估计就是没推送,换其他事件都能监听到,直接打断点到ProviderManager,可以看到.

  1. private AuthenticationEventPublisher eventPublisher;
  2. ...............
  3. if (result == null && this.parent != null) {
  4. try {
  5. parentResult = this.parent.authenticate(authentication);
  6. result = parentResult;
  7. } catch (ProviderNotFoundException var12) {
  8. } catch (AuthenticationException var13) {
  9. parentException = var13;
  10. lastException = var13;
  11. }
  12. }
  13. if (result != null) {
  14. if (this.eraseCredentialsAfterAuthentication && result instanceof CredentialsContainer) {
  15. ((CredentialsContainer)result).eraseCredentials();
  16. }
  17. if (parentResult == null) {
  18. this.eventPublisher.publishAuthenticationSuccess(result);
  19. }
  20. return result;
  21. //Manager自己实现的推送方法
  22. private static final class NullEventPublisher implements AuthenticationEventPublisher {
  23. private NullEventPublisher() {
  24. }
  25. public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {
  26. }
  27. public void publishAuthenticationSuccess(Authentication authentication) {
  28. }
  29. }

看完就明白了,啥玩意,搞个空的等于就推了空气,所以只需要自己在验证成功后自己手工去推一下就好了.

  1. **
  2. * 自定义认证条件
  3. */
  4. @Component
  5. public class UserAuthenticationProvider implements AuthenticationProvider, MessageSourceAware {
  6. protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
  7. protected final Log logger = LogFactory.getLog(this.getClass());
  8. @Autowired
  9. private UserService authUserDetailsService;
  10. @Autowired
  11. private PasswordEncoder passwordEncoder;
  12. @Autowired
  13. private ApplicationEventPublisher publisher;
  14. /**
  15. * @Description 认证处理,返回一个Authentication的实现类则代表认证成功,返回null则代表认证失败
  16. * @Date 2019/7/5 15:19
  17. * @Version 1.0
  18. */
  19. @Override
  20. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  21. //判断访问权限是否为空
  22. if (authentication.getCredentials() == null) {
  23. this.logger.debug("Failed to authenticate since no credentials provided");
  24. throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
  25. }
  26. String presentedPassword = authentication.getCredentials().toString();
  27. //创建UserDetails类
  28. UserDetails user = authUserDetailsService.loadUserByUsername(authentication.getName());
  29. //判断密码是否正确,如果不正确则抛出异常
  30. if (!this.passwordEncoder.matches(presentedPassword, user.getPassword())) {
  31. this.logger.debug("Failed to authenticate since password does not match stored value");
  32. throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
  33. }
  34. //判断用户身份
  35. if (!user.isEnabled()) {
  36. this.logger.debug("Failed to authenticate since user account is disabled");
  37. throw new DisabledException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled"));
  38. } else if (!user.isAccountNonLocked()) {
  39. this.logger.debug("Failed to authenticate since user account is locked");
  40. throw new LockedException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", "User account is locked"));
  41. } else if (!user.isAccountNonExpired()) {
  42. this.logger.debug("Failed to authenticate since user account has expired");
  43. throw new AccountExpiredException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired", "User account has expired"));
  44. }
  45. //获取用户权限信息
  46. Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
  47. /**
  48. * 一定要记住,如果没收到消息,就要自己实现,因为在ProviderManager里面它不会给你实现,而是使用
  49. * 自己空的方法去发布,等于放了个屁,然后就接收不到验证成功的信息,所以要自己实现一个
  50. */
  51. UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user, presentedPassword, authorities);
  52. publisher.publishEvent(new AuthenticationSuccessEvent(usernamePasswordAuthenticationToken));
  53. return usernamePasswordAuthenticationToken;
  54. }
  55. /**
  56. * @Description 如果该AuthenticationProvider支持传入的Authentication对象,则返回true
  57. * @Date 2019/7/5 15:18
  58. * @Version 1.0
  59. */
  60. @Override
  61. public boolean supports(Class<?> aClass) {
  62. return aClass.equals(UsernamePasswordAuthenticationToken.class);
  63. }
  64. @Override
  65. public void setMessageSource(MessageSource messageSource) {
  66. this.messages = new MessageSourceAccessor(messageSource);
  67. }
  68. }

而且要注意,它接收的参数是Authentication authentication,可别直接就把一开始拿到的就放进去,那个只是身份验证,不能直接传进去,否则只能拿到账号和密码,必须要创建一个包装的方法,同时将其他的信息放入.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/913100
推荐阅读
相关标签
  

闽ICP备14008679号