mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 01:01:52 +08:00
去除 Spring Security 的 logout handler,使用自己定义的 logout 接口
This commit is contained in:
parent
baadb5a937
commit
3351ebbbb4
@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocal
|
|||||||
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
|
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
|
||||||
import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
|
import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
|
||||||
import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
|
import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
|
||||||
import cn.iocoder.yudao.framework.security.core.handler.LogoutSuccessHandlerImpl;
|
|
||||||
import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
|
import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
|
||||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||||
@ -19,7 +18,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -63,14 +61,6 @@ public class YudaoSecurityAutoConfiguration {
|
|||||||
return new AccessDeniedHandlerImpl();
|
return new AccessDeniedHandlerImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 退出处理类 Bean
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
public LogoutSuccessHandler logoutSuccessHandler(MultiUserDetailsAuthenticationProvider authenticationProvider) {
|
|
||||||
return new LogoutSuccessHandlerImpl(securityProperties, authenticationProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spring Security 加密器
|
* Spring Security 加密器
|
||||||
* 考虑到安全性,这里采用 BCryptPasswordEncoder 加密器
|
* 考虑到安全性,这里采用 BCryptPasswordEncoder 加密器
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package cn.iocoder.yudao.framework.security.config;
|
package cn.iocoder.yudao.framework.security.config;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
|
import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
|
||||||
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
|
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
|
||||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
@ -17,7 +16,6 @@ import org.springframework.security.config.http.SessionCreationPolicy;
|
|||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -46,11 +44,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
|
|||||||
*/
|
*/
|
||||||
@Resource
|
@Resource
|
||||||
private AccessDeniedHandler accessDeniedHandler;
|
private AccessDeniedHandler accessDeniedHandler;
|
||||||
/**
|
|
||||||
* 退出处理类 Bean
|
|
||||||
*/
|
|
||||||
@Resource
|
|
||||||
private LogoutSuccessHandler logoutSuccessHandler;
|
|
||||||
/**
|
/**
|
||||||
* Token 认证过滤器 Bean
|
* Token 认证过滤器 Bean
|
||||||
*/
|
*/
|
||||||
@ -114,11 +107,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
|
|||||||
.headers().frameOptions().disable().and()
|
.headers().frameOptions().disable().and()
|
||||||
// 一堆自定义的 Spring Security 处理器
|
// 一堆自定义的 Spring Security 处理器
|
||||||
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
|
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
|
||||||
.accessDeniedHandler(accessDeniedHandler).and()
|
.accessDeniedHandler(accessDeniedHandler);
|
||||||
// 登出地址的配置
|
// 登录、登录暂时不使用 Spring Security 的拓展点,主要考虑一方面拓展多用户、多种登录方式相对复杂,一方面用户的学习成本较高
|
||||||
.logout().logoutSuccessHandler(logoutSuccessHandler).logoutRequestMatcher(request -> // 匹配多种用户类型的登出
|
|
||||||
StrUtil.equalsAny(request.getRequestURI(), buildAdminApi("/system/logout"),
|
|
||||||
buildAppApi("/member/logout")));
|
|
||||||
|
|
||||||
// 设置每个请求的权限
|
// 设置每个请求的权限
|
||||||
httpSecurity
|
httpSecurity
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
package cn.iocoder.yudao.framework.security.core.handler;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
|
||||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
|
||||||
import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
|
|
||||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义退出处理器
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
|
|
||||||
|
|
||||||
private final SecurityProperties securityProperties;
|
|
||||||
|
|
||||||
private final MultiUserDetailsAuthenticationProvider authenticationProvider;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
|
|
||||||
// 执行退出
|
|
||||||
String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader());
|
|
||||||
if (StrUtil.isNotBlank(token)) {
|
|
||||||
authenticationProvider.logout(request, token);
|
|
||||||
}
|
|
||||||
// 返回成功
|
|
||||||
ServletUtils.writeJSON(response, CommonResult.success(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,7 +1,10 @@
|
|||||||
package cn.iocoder.yudao.module.member.controller.app.auth;
|
package cn.iocoder.yudao.module.member.controller.app.auth;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
||||||
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||||
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
|
import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
|
||||||
import cn.iocoder.yudao.module.member.service.auth.MemberAuthService;
|
import cn.iocoder.yudao.module.member.service.auth.MemberAuthService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@ -13,6 +16,7 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
@ -30,6 +34,9 @@ public class AppAuthController {
|
|||||||
@Resource
|
@Resource
|
||||||
private MemberAuthService authService;
|
private MemberAuthService authService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SecurityProperties securityProperties;
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@ApiOperation("使用手机 + 密码登录")
|
@ApiOperation("使用手机 + 密码登录")
|
||||||
public CommonResult<AppAuthLoginRespVO> login(@RequestBody @Valid AppAuthLoginReqVO reqVO) {
|
public CommonResult<AppAuthLoginRespVO> login(@RequestBody @Valid AppAuthLoginReqVO reqVO) {
|
||||||
@ -37,6 +44,16 @@ public class AppAuthController {
|
|||||||
return success(AppAuthLoginRespVO.builder().token(token).build());
|
return success(AppAuthLoginRespVO.builder().token(token).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/logout")
|
||||||
|
@ApiOperation("登出系统")
|
||||||
|
public CommonResult<Boolean> logout(HttpServletRequest request) {
|
||||||
|
String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader());
|
||||||
|
if (StrUtil.isNotBlank(token)) {
|
||||||
|
authService.logout(token);
|
||||||
|
}
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/sms-login")
|
@PostMapping("/sms-login")
|
||||||
@ApiOperation("使用手机 + 验证码登录")
|
@ApiOperation("使用手机 + 验证码登录")
|
||||||
public CommonResult<AppAuthLoginRespVO> smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) {
|
public CommonResult<AppAuthLoginRespVO> smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) {
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* 属于 system 模块的 framework 封装
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.member.framework;
|
@ -0,0 +1,28 @@
|
|||||||
|
package cn.iocoder.yudao.module.member.framework.security.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Member 模块的 Security 配置
|
||||||
|
*/
|
||||||
|
@Configuration("memberSecurityConfiguration")
|
||||||
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
|
@Bean("memberAuthorizeRequestsCustomizer")
|
||||||
|
public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
|
||||||
|
return new AuthorizeRequestsCustomizer() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
|
||||||
|
// 登录的接口
|
||||||
|
registry.antMatchers(buildAdminApi("/member/auth/logout")).permitAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* 占位
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.module.member.framework.security.core;
|
@ -1,9 +1,12 @@
|
|||||||
package cn.iocoder.yudao.module.system.controller.admin.auth;
|
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.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
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.controller.admin.auth.vo.auth.*;
|
||||||
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
|
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
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 org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -52,15 +56,28 @@ public class AuthController {
|
|||||||
@Resource
|
@Resource
|
||||||
private SocialUserService socialUserService;
|
private SocialUserService socialUserService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SecurityProperties securityProperties;
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@ApiOperation("使用账号密码登录")
|
@ApiOperation("使用账号密码登录")
|
||||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||||
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
|
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
|
||||||
String token = authService.login(reqVO, getClientIP(), getUserAgent());
|
String token = authService.login(reqVO, getClientIP(), getUserAgent());
|
||||||
// 返回结果
|
|
||||||
return success(AuthLoginRespVO.builder().token(token).build());
|
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")
|
@GetMapping("/get-permission-info")
|
||||||
@ApiOperation("获取登录用户的权限信息")
|
@ApiOperation("获取登录用户的权限信息")
|
||||||
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
|
public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() {
|
||||||
@ -130,7 +147,6 @@ public class AuthController {
|
|||||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||||
public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) {
|
public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) {
|
||||||
String token = authService.socialQuickLogin(reqVO, getClientIP(), getUserAgent());
|
String token = authService.socialQuickLogin(reqVO, getClientIP(), getUserAgent());
|
||||||
// 返回结果
|
|
||||||
return success(AuthLoginRespVO.builder().token(token).build());
|
return success(AuthLoginRespVO.builder().token(token).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +155,6 @@ public class AuthController {
|
|||||||
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志
|
||||||
public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) {
|
public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) {
|
||||||
String token = authService.socialBindLogin(reqVO, getClientIP(), getUserAgent());
|
String token = authService.socialBindLogin(reqVO, getClientIP(), getUserAgent());
|
||||||
// 返回结果
|
|
||||||
return success(AuthLoginRespVO.builder().token(token).build());
|
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) {
|
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
|
||||||
// 登录的接口
|
// 登录的接口
|
||||||
registry.antMatchers(buildAdminApi("/system/auth/login")).permitAll();
|
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-auth-redirect")).permitAll();
|
||||||
registry.antMatchers(buildAdminApi("/system/auth/social-quick-login")).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);
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
@ -26,7 +26,7 @@ export function getInfo() {
|
|||||||
// 退出方法
|
// 退出方法
|
||||||
export function logout() {
|
export function logout() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/logout',
|
url: '/system/auth/logout',
|
||||||
method: 'post'
|
method: 'post'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user