From 031d1c5a7c680bfcf2b9a4a98e9d0ae0c613ff51 Mon Sep 17 00:00:00 2001 From: zhuo <2089219845@qq.com> Date: 星期六, 15 三月 2025 11:42:24 +0800 Subject: [PATCH] 新增无需密码获取用户登录信息 --- ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java | 4 /dev/null | 36 ------- ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java | 56 +++++++++- ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationProvider.java | 42 ++++++++ ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationToken.java | 63 ++++++++++++ ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsByOpenIdServiceImpl.java | 47 +++++++++ ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java | 25 ++++ 7 files changed, 226 insertions(+), 47 deletions(-) diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/LocalDateTimeSerializerConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/LocalDateTimeSerializerConfig.java deleted file mode 100644 index 98a8763..0000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/LocalDateTimeSerializerConfig.java +++ /dev/null @@ -1,36 +0,0 @@ -//package com.ruoyi.framework.config; -// -//import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; -//import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; -//import org.springframework.beans.factory.annotation.Value; -//import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -// -//import java.time.LocalDateTime; -//import java.time.format.DateTimeFormatter; -// -//@Configuration -//public class LocalDateTimeSerializerConfig { -// @Value("${spring.jackson.date-format}") -// private String pattern; -// -// @Bean -// public LocalDateTimeSerializer localDateTimeSerializer() { -// return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern)); -// } -// -// @Bean -// public LocalDateTimeDeserializer localDateTimeDeserializer() { -// return new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(pattern)); -// } -// -// @Bean -// public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { -// return builder -> { -// builder.serializerByType(LocalDateTime.class, localDateTimeSerializer()); -// builder.deserializerByType(LocalDateTime.class, localDateTimeDeserializer()); -// builder.simpleDateFormat(pattern); -// }; -// } -//} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index 974a5e2..f4a7045 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -1,10 +1,13 @@ package com.ruoyi.framework.config; +import com.ruoyi.framework.web.ssoAuth.SsoCodeAuthenticationProvider; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; @@ -21,6 +24,9 @@ import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl; import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl; +import java.util.ArrayList; +import java.util.List; + /** * spring security閰嶇疆 * @@ -34,7 +40,15 @@ * 鑷畾涔夌敤鎴疯璇侀�昏緫 */ @Autowired + @Qualifier("UserDetailsServiceImpl") private UserDetailsService userDetailsService; + + /** + * sso鑷畾涔夋牎楠� + */ + @Autowired + @Qualifier("UserDetailsByOpenIdServiceImpl") + private UserDetailsService userDetailsServiceByOpenId; /** * 璁よ瘉澶辫触澶勭悊绫� @@ -75,7 +89,16 @@ DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(userDetailsService); daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder()); - return new ProviderManager(daoAuthenticationProvider); + + // sso鐧婚檰閴存潈 Provider + SsoCodeAuthenticationProvider wxCodeAuthenticationProvider = new SsoCodeAuthenticationProvider(); + wxCodeAuthenticationProvider.setUserDetailsService(userDetailsServiceByOpenId); + List<AuthenticationProvider> providers = new ArrayList<>(); + + providers.add(wxCodeAuthenticationProvider); + providers.add(daoAuthenticationProvider); + + return new ProviderManager(providers); } /** diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java index b6841dd..c5da313 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java @@ -9,6 +9,7 @@ import com.ruoyi.common.core.domain.entity.User; import com.ruoyi.framework.model.SsoOauthTokenModel; import com.ruoyi.framework.model.SsoUserInfoModel; +import com.ruoyi.framework.web.ssoAuth.SsoCodeAuthenticationToken; import com.ruoyi.system.mapper.UserMapper; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; @@ -93,9 +94,6 @@ @Autowired private RedisTemplate redisTemplate; - - @Autowired - private UserMapper userMapper; /** * 鐧诲綍楠岃瘉 @@ -234,26 +232,68 @@ // 鑾峰彇鍗曠偣鐧诲綍token SsoOauthTokenModel tokenModel = this.getSsoAccessToken(code); if (tokenModel == null) { - return null; + throw new RuntimeException("鍗曠偣鐧诲綍楠岃瘉澶辫触"); } // 鑾峰彇鍗曠偣鐧诲綍鐢ㄦ埛淇℃伅 SsoUserInfoModel userInfo = this.getSsoUserInfo(tokenModel.getAccess_token()); if (userInfo == null) { - return null; + throw new RuntimeException("鍗曠偣鐧诲綍楠岃瘉澶辫触"); } // 鏌ヨ鏈湴鐢ㄦ埛淇℃伅 + LoginUser loginUser = this.getSsoLoginToken(userInfo.getEmployeeId()); + recordLoginInfo(loginUser.getUserId()); - - + // 鍒涘缓鐧诲綍淇℃伅 AsyncManager.me().execute(AsyncFactory.recordLogininfor(userInfo.getEmployeeId(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.single.login.success"))); redisTemplate.opsForValue().set("ssoOauthToken:idToken:" + userInfo.getEmployeeId(), tokenModel.getId_token(), 3, TimeUnit.DAYS); // 鐢熸垚token - return tokenService.createToken(null); + return tokenService.createToken(loginUser); } /** + * ***** 鑾峰彇鏈湴鐢ㄦ埛淇℃伅 ***** + * @param username + * @return + */ + public LoginUser getSsoLoginToken(String username) { + // 鐢ㄦ埛楠岃瘉 + Authentication authentication = null; + SysUser sysUser = sysUserService.selectUserByUserName(username); + if (sysUser == null) { + throw new ServiceException("鐢ㄦ埛涓嶅瓨鍦�"); + } + try + { + // 鏃犻渶瀵嗙爜鑾峰彇鐢ㄦ埛淇℃伅 + authentication = authenticationManager.authenticate(new SsoCodeAuthenticationToken(username)); + } + catch (Exception e) + { + if (e instanceof BadCredentialsException) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); + throw new UserPasswordNotMatchException(); + } + else + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); + throw new ServiceException(e.getMessage()); + } + } + finally + { + AuthenticationContextHolder.clearContext(); + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + return (LoginUser) authentication.getPrincipal(); + + } + + + + /** * **** 鑾峰彇鍗曠偣鐧诲綍token **** * @param code * @return diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsByOpenIdServiceImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsByOpenIdServiceImpl.java new file mode 100644 index 0000000..a97d073 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsByOpenIdServiceImpl.java @@ -0,0 +1,47 @@ +package com.ruoyi.framework.web.service; + +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.UserStatus; +import com.ruoyi.common.exception.base.BaseException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.web.service.SysPermissionService; +import com.ruoyi.system.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service("UserDetailsByOpenIdServiceImpl") +public class UserDetailsByOpenIdServiceImpl implements UserDetailsService { + + + + @Autowired + private ISysUserService userService; + + @Autowired + private SysPermissionService permissionService; + + @Override + public UserDetails loadUserByUsername(String openId) throws UsernameNotFoundException { + SysUser user = userService.selectUserByUserName(openId); + if (StringUtils.isNull(user)) { + + throw new UsernameNotFoundException("鐧诲綍鐢ㄦ埛锛�" + openId + " 涓嶅瓨鍦�"); + } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { + + throw new BaseException("瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿锛�" + openId + " 宸茶鍒犻櫎"); + } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + + throw new BaseException("瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿锛�" + openId + " 宸插仠鐢�"); + } + // 鍜岃嫢渚濈殑鍖哄埆 鏄病鏈夐獙璇佸瘑鐮� + return createLoginUser(user); + } + + public UserDetails createLoginUser(SysUser user) { + return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user)); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java index 5dcdf90..f6dac10 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java @@ -20,14 +20,14 @@ * * @author ruoyi */ -@Service +@Service("UserDetailsServiceImpl") public class UserDetailsServiceImpl implements UserDetailsService { private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class); @Autowired private ISysUserService userService; - + @Autowired private SysPasswordService passwordService; diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationProvider.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationProvider.java new file mode 100644 index 0000000..f882b7b --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationProvider.java @@ -0,0 +1,42 @@ +package com.ruoyi.framework.web.ssoAuth; + +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.AuthenticationException; +public class SsoCodeAuthenticationProvider implements AuthenticationProvider { + + private UserDetailsService userDetailsService; + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + SsoCodeAuthenticationToken authenticationToken = (SsoCodeAuthenticationToken) authentication; + + String openId = (String) authenticationToken.getPrincipal(); + + UserDetails userDetails = userDetailsService.loadUserByUsername(openId); + + // 姝ゆ椂閴存潈鎴愬姛鍚庯紝搴斿綋閲嶆柊 new 涓�涓嫢鏈夐壌鏉冪殑 authenticationResult 杩斿洖 + SsoCodeAuthenticationToken authenticationResult = new SsoCodeAuthenticationToken(userDetails, userDetails.getAuthorities()); + + authenticationResult.setDetails(authenticationToken.getDetails()); + + return authenticationResult; + } + + + @Override + public boolean supports(Class<?> authentication) { + // 鍒ゆ柇 authentication 鏄笉鏄� WxCodeAuthenticationToken 鐨勫瓙绫绘垨瀛愭帴鍙� + return SsoCodeAuthenticationToken.class.isAssignableFrom(authentication); + } + + public UserDetailsService getUserDetailsService() { + return userDetailsService; + } + + public void setUserDetailsService(UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationToken.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationToken.java new file mode 100644 index 0000000..b783f36 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationToken.java @@ -0,0 +1,63 @@ +package com.ruoyi.framework.web.ssoAuth; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.SpringSecurityCoreVersion; + +import java.util.Collection; + +public class SsoCodeAuthenticationToken extends AbstractAuthenticationToken { + + private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; + + /** + * 鍦� UsernamePasswordAuthenticationToken 涓瀛楁浠h〃鐧诲綍鐨勭敤鎴峰悕锛� + * 鍦ㄨ繖閲屽氨浠h〃鐧诲綍鐨刼penId + */ + private final Object principal; + + /** + * 鏋勫缓涓�涓病鏈夐壌鏉冪殑 SsoCodeAuthenticationToken + */ + public SsoCodeAuthenticationToken(Object principal) { + super(null); + this.principal = principal; + setAuthenticated(false); + } + + /** + * 鏋勫缓鎷ユ湁閴存潈鐨� SsoCodeAuthenticationToken + */ + public SsoCodeAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) { + super(authorities); + this.principal = principal; + // must use super, as we override + super.setAuthenticated(true); + } + + @Override + public Object getCredentials() { + return null; + } + + @Override + public Object getPrincipal() { + return this.principal; + } + + @Override + public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { + if (isAuthenticated) { + throw new IllegalArgumentException( + "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); + } + + super.setAuthenticated(false); + } + + @Override + public void eraseCredentials() { + super.eraseCredentials(); + } + +} -- Gitblit v1.9.3