mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10:18:42 +08:00 
			
		
		
		
	去除 Spring Security 的 logout handler,使用自己定义的 logout 接口
This commit is contained in:
		| @@ -1,9 +1,12 @@ | ||||
| package cn.iocoder.yudao.module.system.controller.admin.auth; | ||||
|  | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | ||||
| import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||||
| import cn.iocoder.yudao.framework.security.config.SecurityProperties; | ||||
| import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | ||||
| import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; | ||||
| import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; | ||||
| import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | ||||
| @@ -24,6 +27,7 @@ import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.validation.Valid; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| @@ -52,15 +56,28 @@ public class AuthController { | ||||
|     @Resource | ||||
|     private SocialUserService socialUserService; | ||||
|  | ||||
|     @Resource | ||||
|     private SecurityProperties securityProperties; | ||||
|  | ||||
|     @PostMapping("/login") | ||||
|     @ApiOperation("使用账号密码登录") | ||||
|     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||||
|     public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) { | ||||
|         String token = authService.login(reqVO, getClientIP(), getUserAgent()); | ||||
|         // 返回结果 | ||||
|         return success(AuthLoginRespVO.builder().token(token).build()); | ||||
|     } | ||||
|  | ||||
|     @PostMapping("/logout") | ||||
|     @ApiOperation("登出系统") | ||||
|     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||||
|     public CommonResult<Boolean> logout(HttpServletRequest request) { | ||||
|         String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); | ||||
|         if (StrUtil.isNotBlank(token)) { | ||||
|             authService.logout(token); | ||||
|         } | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/get-permission-info") | ||||
|     @ApiOperation("获取登录用户的权限信息") | ||||
|     public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() { | ||||
| @@ -130,7 +147,6 @@ public class AuthController { | ||||
|     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||||
|     public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) { | ||||
|         String token = authService.socialQuickLogin(reqVO, getClientIP(), getUserAgent()); | ||||
|         // 返回结果 | ||||
|         return success(AuthLoginRespVO.builder().token(token).build()); | ||||
|     } | ||||
|  | ||||
| @@ -139,7 +155,6 @@ public class AuthController { | ||||
|     @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||||
|     public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) { | ||||
|         String token = authService.socialBindLogin(reqVO, getClientIP(), getUserAgent()); | ||||
|         // 返回结果 | ||||
|         return success(AuthLoginRespVO.builder().token(token).build()); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,55 @@ | ||||
| package cn.iocoder.yudao.module.system.dal.dataobject.auth; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.experimental.Accessors; | ||||
|  | ||||
| import java.util.Date; | ||||
|  | ||||
| /** | ||||
|  * OAuth2 访问令牌 | ||||
|  * | ||||
|  */ | ||||
| @TableName("system_oauth2_access_token") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @Accessors(chain = true) | ||||
| public class OAuth2AccessTokenDO extends BaseDO { | ||||
|  | ||||
|     /** | ||||
|      * 编号,数据库字典 | ||||
|      */ | ||||
|     private Long id; | ||||
|     /** | ||||
|      * 访问令牌 | ||||
|      */ | ||||
|     private String accessToken; | ||||
|     /** | ||||
|      * 用户编号 | ||||
|      */ | ||||
|     private Long userId; | ||||
|     /** | ||||
|      * 用户类型 | ||||
|      * | ||||
|      * 枚举 {@link UserTypeEnum} | ||||
|      */ | ||||
|     private Integer userType; | ||||
|     /** | ||||
|      * 刷新令牌 | ||||
|      * | ||||
|      * 关联 {@link OAuth2RefreshTokenDO#getRefreshToken()} | ||||
|      */ | ||||
|     private String refreshToken; | ||||
|     /** | ||||
|      * 过期时间 | ||||
|      */ | ||||
|     private Date expiresTime; | ||||
|     /** | ||||
|      * 创建 IP | ||||
|      */ | ||||
|     private String createIp; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,49 @@ | ||||
| package cn.iocoder.yudao.module.system.dal.dataobject.auth; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.experimental.Accessors; | ||||
|  | ||||
| import java.util.Date; | ||||
|  | ||||
| /** | ||||
|  * OAuth2 刷新令牌 | ||||
|  * | ||||
|  */ | ||||
| @TableName("system_oauth2_refresh_token") | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @Accessors(chain = true) | ||||
| public class OAuth2RefreshTokenDO extends BaseDO { | ||||
|  | ||||
|     /** | ||||
|      * 编号,数据库字典 | ||||
|      */ | ||||
|     private Long id; | ||||
|     /** | ||||
|      * 刷新令牌 | ||||
|      */ | ||||
|     private String refreshToken; | ||||
|     /** | ||||
|      * 用户编号 | ||||
|      */ | ||||
|     private Integer userId; | ||||
|     /** | ||||
|      * 用户类型 | ||||
|      * | ||||
|      * 枚举 {@link UserTypeEnum} | ||||
|      */ | ||||
|     private Integer userType; | ||||
|     /** | ||||
|      * 过期时间 | ||||
|      */ | ||||
|     private Date expiresTime; | ||||
|     /** | ||||
|      * 创建 IP | ||||
|      */ | ||||
|     private String createIp; | ||||
|  | ||||
| } | ||||
| @@ -20,6 +20,7 @@ public class SecurityConfiguration { | ||||
|             public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { | ||||
|                 // 登录的接口 | ||||
|                 registry.antMatchers(buildAdminApi("/system/auth/login")).permitAll(); | ||||
|                 registry.antMatchers(buildAdminApi("/system/auth/logout")).permitAll(); | ||||
|                 // 社交登陆的接口 | ||||
|                 registry.antMatchers(buildAdminApi("/system/auth/social-auth-redirect")).permitAll(); | ||||
|                 registry.antMatchers(buildAdminApi("/system/auth/social-quick-login")).permitAll(); | ||||
|   | ||||
| @@ -0,0 +1,18 @@ | ||||
| package cn.iocoder.yudao.module.system.service.auth; | ||||
|  | ||||
| /** | ||||
|  * OAuth2.0 Service 接口 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| public interface OAuth2Service { | ||||
|  | ||||
| //    OAuth2AccessTokenDO createAccessToken(Long userId, Integer userType, String createIp); | ||||
| // | ||||
| //    OAuth2AccessTokenRespDTO checkAccessToken(String accessToken); | ||||
| // | ||||
| //    OAuth2AccessTokenRespDTO refreshAccessToken(OAuth2RefreshAccessTokenReqDTO refreshAccessTokenDTO); | ||||
| // | ||||
| //    void removeToken(OAuth2RemoveTokenByUserReqDTO removeTokenDTO); | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,143 @@ | ||||
| package cn.iocoder.yudao.module.system.service.auth; | ||||
|  | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| /** | ||||
|  * OAuth2.0 Service 实现类 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @Service | ||||
| public class OAuth2ServiceImpl implements OAuth2Service { | ||||
|  | ||||
| //    @Autowired | ||||
| //    private SystemBizProperties systemBizProperties; | ||||
| // | ||||
| //    @Autowired | ||||
| //    private OAuth2AccessTokenMapper oauth2AccessTokenMapper; | ||||
| //    @Autowired | ||||
| //    private OAuth2RefreshTokenMapper oauth2RefreshTokenMapper; | ||||
| // | ||||
| //    @Autowired | ||||
| //    private OAuth2AccessTokenRedisDAO oauth2AccessTokenRedisDAO; | ||||
| // | ||||
| //    @Override | ||||
| //    @Transactional | ||||
| //    public OAuth2AccessTokenRespDTO createAccessToken(OAuth2CreateAccessTokenReqDTO createAccessTokenDTO) { | ||||
| //        // 创建刷新令牌 + 访问令牌 | ||||
| //        OAuth2RefreshTokenDO refreshTokenDO = createOAuth2RefreshToken(createAccessTokenDTO.getUserId(), | ||||
| //                createAccessTokenDTO.getUserType(), createAccessTokenDTO.getCreateIp()); | ||||
| //        OAuth2AccessTokenDO accessTokenDO = createOAuth2AccessToken(refreshTokenDO, createAccessTokenDTO.getCreateIp()); | ||||
| //        // 返回访问令牌 | ||||
| //        return OAuth2Convert.INSTANCE.convert(accessTokenDO); | ||||
| //    } | ||||
| // | ||||
| //    @Override | ||||
| //    @Transactional | ||||
| //    public OAuth2AccessTokenRespDTO checkAccessToken(String accessToken) { | ||||
| //        OAuth2AccessTokenDO accessTokenDO = this.getOAuth2AccessToken(accessToken); | ||||
| //        if (accessTokenDO == null) { // 不存在 | ||||
| //            throw ServiceExceptionUtil.exception(OAUTH2_ACCESS_TOKEN_NOT_FOUND); | ||||
| //        } | ||||
| //        if (accessTokenDO.getExpiresTime().getTime() < System.currentTimeMillis()) { // 已过期 | ||||
| //            throw ServiceExceptionUtil.exception(OAUTH2_ACCESS_TOKEN_TOKEN_EXPIRED); | ||||
| //        } | ||||
| //        // 返回访问令牌 | ||||
| //        return OAuth2Convert.INSTANCE.convert(accessTokenDO); | ||||
| //    } | ||||
| // | ||||
| //    @Override | ||||
| //    @Transactional | ||||
| //    public OAuth2AccessTokenRespDTO refreshAccessToken(OAuth2RefreshAccessTokenReqDTO refreshAccessTokenDTO) { | ||||
| //        OAuth2RefreshTokenDO refreshTokenDO = oauth2RefreshTokenMapper.selectById(refreshAccessTokenDTO.getRefreshToken()); | ||||
| //        // 校验刷新令牌是否合法 | ||||
| //        if (refreshTokenDO == null) { // 不存在 | ||||
| //            throw ServiceExceptionUtil.exception(OAUTH2_REFRESH_TOKEN_NOT_FOUND); | ||||
| //        } | ||||
| //        if (refreshTokenDO.getExpiresTime().getTime() < System.currentTimeMillis()) { // 已过期 | ||||
| //            throw ServiceExceptionUtil.exception(OAUTH_REFRESH_TOKEN_EXPIRED); | ||||
| //        } | ||||
| // | ||||
| //        // 标记 refreshToken 对应的 accessToken 都不合法 | ||||
| //        // 这块的实现,参考了 Spring Security OAuth2 的代码 | ||||
| //        List<OAuth2AccessTokenDO> accessTokenDOs = oauth2AccessTokenMapper.selectListByRefreshToken(refreshAccessTokenDTO.getRefreshToken()); | ||||
| //        accessTokenDOs.forEach(accessTokenDO -> deleteOAuth2AccessToken(accessTokenDO.getId())); | ||||
| // | ||||
| //        // 创建访问令牌 | ||||
| //        OAuth2AccessTokenDO oauth2AccessTokenDO = createOAuth2AccessToken(refreshTokenDO, refreshAccessTokenDTO.getCreateIp()); | ||||
| //        // 返回访问令牌 | ||||
| //        return OAuth2Convert.INSTANCE.convert(oauth2AccessTokenDO); | ||||
| //    } | ||||
| // | ||||
| //    @Override | ||||
| //    @Transactional | ||||
| //    public void removeToken(OAuth2RemoveTokenByUserReqDTO removeTokenDTO) { | ||||
| //        // 删除 Access Token | ||||
| //        OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenMapper.selectByUserIdAndUserType( | ||||
| //                removeTokenDTO.getUserId(), removeTokenDTO.getUserType()); | ||||
| //        if (accessTokenDO != null) { | ||||
| //            this.deleteOAuth2AccessToken(accessTokenDO.getId()); | ||||
| //        } | ||||
| // | ||||
| //        // 删除 Refresh Token | ||||
| //        oauth2RefreshTokenMapper.deleteByUserIdAndUserType(removeTokenDTO.getUserId(), removeTokenDTO.getUserType()); | ||||
| //    } | ||||
| // | ||||
| //    private OAuth2AccessTokenDO createOAuth2AccessToken(OAuth2RefreshTokenDO refreshTokenDO, String createIp) { | ||||
| //        OAuth2AccessTokenDO accessToken = new OAuth2AccessTokenDO() | ||||
| //                .setId(generateAccessToken()) | ||||
| //                .setUserId(refreshTokenDO.getUserId()).setUserType(refreshTokenDO.getUserType()) | ||||
| //                .setRefreshToken(refreshTokenDO.getId()) | ||||
| //                .setExpiresTime(new Date(System.currentTimeMillis() + systemBizProperties.getAccessTokenExpireTimeMillis())) | ||||
| //                .setCreateIp(createIp); | ||||
| //        oauth2AccessTokenMapper.insert(accessToken); | ||||
| //        return accessToken; | ||||
| //    } | ||||
| // | ||||
| //    private OAuth2RefreshTokenDO createOAuth2RefreshToken(Integer userId, Integer userType, String createIp) { | ||||
| //        OAuth2RefreshTokenDO refreshToken = new OAuth2RefreshTokenDO() | ||||
| //                .setId(generateRefreshToken()) | ||||
| //                .setUserId(userId).setUserType(userType) | ||||
| //                .setExpiresTime(new Date(System.currentTimeMillis() + systemBizProperties.getRefreshTokenExpireTimeMillis())) | ||||
| //                .setCreateIp(createIp); | ||||
| //        oauth2RefreshTokenMapper.insert(refreshToken); | ||||
| //        return refreshToken; | ||||
| //    } | ||||
| // | ||||
| //    private OAuth2AccessTokenDO getOAuth2AccessToken(String accessToken) { | ||||
| //        // 优先从 Redis 中获取 | ||||
| //        OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenRedisDAO.get(accessToken); | ||||
| //        if (accessTokenDO != null) { | ||||
| //            return accessTokenDO; | ||||
| //        } | ||||
| // | ||||
| //        // 获取不到,从 MySQL 中获取 | ||||
| //        accessTokenDO = oauth2AccessTokenMapper.selectById(accessToken); | ||||
| //        // 如果在 MySQL 存在,则往 Redis 中写入 | ||||
| //        if (accessTokenDO != null) { | ||||
| //            oauth2AccessTokenRedisDAO.set(accessTokenDO); | ||||
| //        } | ||||
| //        return accessTokenDO; | ||||
| //    } | ||||
| // | ||||
| //    /** | ||||
| //     * 删除 accessToken 的 MySQL 与 Redis 的数据 | ||||
| //     * | ||||
| //     * @param accessToken 访问令牌 | ||||
| //     */ | ||||
| //    private void deleteOAuth2AccessToken(String accessToken) { | ||||
| //        // 删除 MySQL | ||||
| //        oauth2AccessTokenMapper.deleteById(accessToken); | ||||
| //        // 删除 Redis | ||||
| //        oauth2AccessTokenRedisDAO.delete(accessToken); | ||||
| //    } | ||||
| // | ||||
| //    private static String generateAccessToken() { | ||||
| //        return StringUtils.uuid(true); | ||||
| //    } | ||||
| // | ||||
| //    private static String generateRefreshToken() { | ||||
| //        return StringUtils.uuid(true); | ||||
| //    } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV