From 3351ebbbb4ea4971a6fde9d0b9ba97913cc46137 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 8 May 2022 00:38:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8E=BB=E9=99=A4=20Spring=20Security=20?= =?UTF-8?q?=E7=9A=84=20logout=20handler=EF=BC=8C=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E8=87=AA=E5=B7=B1=E5=AE=9A=E4=B9=89=E7=9A=84=20logout=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YudaoSecurityAutoConfiguration.java | 10 -- .../YudaoWebSecurityConfigurerAdapter.java | 14 +- .../handler/LogoutSuccessHandlerImpl.java | 40 ----- .../app/auth/AppAuthController.java | 17 +++ .../module/member/framework/package-info.java | 6 + .../config/SecurityConfiguration.java | 28 ++++ .../framework/security/core/package-info.java | 4 + .../controller/admin/auth/AuthController.java | 21 ++- .../dataobject/auth/OAuth2AccessTokenDO.java | 55 +++++++ .../dataobject/auth/OAuth2RefreshTokenDO.java | 49 ++++++ .../config/SecurityConfiguration.java | 1 + .../system/service/auth/OAuth2Service.java | 18 +++ .../service/auth/OAuth2ServiceImpl.java | 143 ++++++++++++++++++ yudao-ui-admin/src/api/login.js | 2 +- 14 files changed, 342 insertions(+), 66 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/config/SecurityConfiguration.java create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/core/package-info.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2AccessTokenDO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2RefreshTokenDO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2Service.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2ServiceImpl.java diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java index 1db4797d4c..af728045c9 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java @@ -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.handler.AccessDeniedHandlerImpl; 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.web.config.WebProperties; 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.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import javax.annotation.Resource; import java.util.List; @@ -63,14 +61,6 @@ public class YudaoSecurityAutoConfiguration { return new AccessDeniedHandlerImpl(); } - /** - * 退出处理类 Bean - */ - @Bean - public LogoutSuccessHandler logoutSuccessHandler(MultiUserDetailsAuthenticationProvider authenticationProvider) { - return new LogoutSuccessHandlerImpl(securityProperties, authenticationProvider); - } - /** * Spring Security 加密器 * 考虑到安全性,这里采用 BCryptPasswordEncoder 加密器 diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java index 0c0dd3278f..c0bc2a0560 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java @@ -1,6 +1,5 @@ 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.filter.TokenAuthenticationFilter; 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.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import javax.annotation.Resource; import java.util.List; @@ -46,11 +44,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap */ @Resource private AccessDeniedHandler accessDeniedHandler; - /** - * 退出处理类 Bean - */ - @Resource - private LogoutSuccessHandler logoutSuccessHandler; /** * Token 认证过滤器 Bean */ @@ -114,11 +107,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap .headers().frameOptions().disable().and() // 一堆自定义的 Spring Security 处理器 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) - .accessDeniedHandler(accessDeniedHandler).and() - // 登出地址的配置 - .logout().logoutSuccessHandler(logoutSuccessHandler).logoutRequestMatcher(request -> // 匹配多种用户类型的登出 - StrUtil.equalsAny(request.getRequestURI(), buildAdminApi("/system/logout"), - buildAppApi("/member/logout"))); + .accessDeniedHandler(accessDeniedHandler); + // 登录、登录暂时不使用 Spring Security 的拓展点,主要考虑一方面拓展多用户、多种登录方式相对复杂,一方面用户的学习成本较高 // 设置每个请求的权限 httpSecurity diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java deleted file mode 100644 index 1a642304ca..0000000000 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java +++ /dev/null @@ -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)); - } - -} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java index 3a78b39774..696ead921e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java @@ -1,7 +1,10 @@ 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.security.config.SecurityProperties; 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.service.auth.MemberAuthService; import io.swagger.annotations.Api; @@ -13,6 +16,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 static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -30,6 +34,9 @@ public class AppAuthController { @Resource private MemberAuthService authService; + @Resource + private SecurityProperties securityProperties; + @PostMapping("/login") @ApiOperation("使用手机 + 密码登录") public CommonResult login(@RequestBody @Valid AppAuthLoginReqVO reqVO) { @@ -37,6 +44,16 @@ public class AppAuthController { return success(AppAuthLoginRespVO.builder().token(token).build()); } + @PostMapping("/logout") + @ApiOperation("登出系统") + public CommonResult logout(HttpServletRequest request) { + String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); + if (StrUtil.isNotBlank(token)) { + authService.logout(token); + } + return success(true); + } + @PostMapping("/sms-login") @ApiOperation("使用手机 + 验证码登录") public CommonResult smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) { diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java new file mode 100644 index 0000000000..02d61331af --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 system 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.member.framework; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/config/SecurityConfiguration.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/config/SecurityConfiguration.java new file mode 100644 index 0000000000..c284b35d6d --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/config/SecurityConfiguration.java @@ -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.ExpressionInterceptUrlRegistry registry) { + // 登录的接口 + registry.antMatchers(buildAdminApi("/member/auth/logout")).permitAll(); + } + + }; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/core/package-info.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/core/package-info.java new file mode 100644 index 0000000000..3abf5630f8 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.member.framework.security.core; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java index 0e26674f80..2b494a9a18 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java @@ -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 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 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 getPermissionInfo() { @@ -130,7 +147,6 @@ public class AuthController { @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 public CommonResult 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 socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) { String token = authService.socialBindLogin(reqVO, getClientIP(), getUserAgent()); - // 返回结果 return success(AuthLoginRespVO.builder().token(token).build()); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2AccessTokenDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2AccessTokenDO.java new file mode 100644 index 0000000000..63e251335c --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2AccessTokenDO.java @@ -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; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2RefreshTokenDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2RefreshTokenDO.java new file mode 100644 index 0000000000..42824f2977 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2RefreshTokenDO.java @@ -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; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java index 567c98775f..9a7eb97286 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SecurityConfiguration.java @@ -20,6 +20,7 @@ public class SecurityConfiguration { public void customize(ExpressionUrlAuthorizationConfigurer.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(); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2Service.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2Service.java new file mode 100644 index 0000000000..030bef8f67 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2Service.java @@ -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); + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2ServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2ServiceImpl.java new file mode 100644 index 0000000000..7718f36e17 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2ServiceImpl.java @@ -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 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); +// } + +} diff --git a/yudao-ui-admin/src/api/login.js b/yudao-ui-admin/src/api/login.js index 33222bc1dd..77fbe9f9d0 100644 --- a/yudao-ui-admin/src/api/login.js +++ b/yudao-ui-admin/src/api/login.js @@ -26,7 +26,7 @@ export function getInfo() { // 退出方法 export function logout() { return request({ - url: '/system/logout', + url: '/system/auth/logout', method: 'post' }) }