zhuo
2025-03-15 031d1c5a7c680bfcf2b9a4a98e9d0ae0c613ff51
新增无需密码获取用户登录信息
已修改3个文件
已删除1个文件
已添加3个文件
271 ■■■■ 文件已修改
ruoyi-framework/src/main/java/com/ruoyi/framework/config/LocalDateTimeSerializerConfig.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsByOpenIdServiceImpl.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationProvider.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/ssoAuth/SsoCodeAuthenticationToken.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/LocalDateTimeSerializerConfig.java
ÎļþÒÑɾ³ý
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);
    }
    /**
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
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));
    }
}
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java
@@ -20,7 +20,7 @@
 *
 * @author ruoyi
 */
@Service
@Service("UserDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService
{
    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
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;
    }
}
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 ä¸­è¯¥å­—段代表登录的用户名,
     * åœ¨è¿™é‡Œå°±ä»£è¡¨ç™»å½•çš„openId
     */
    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();
    }
}