Commit 3351ebbbb4ea4971a6fde9d0b9ba97913cc46137
1 parent
baadb5a9
去除 Spring Security 的 logout handler,使用自己定义的 logout 接口
Showing
14 changed files
with
342 additions
and
66 deletions
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 | @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocal | ||
| 6 | import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter; | 6 | import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter; |
| 7 | import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl; | 7 | import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl; |
| 8 | import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl; | 8 | import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl; |
| 9 | -import cn.iocoder.yudao.framework.security.core.handler.LogoutSuccessHandlerImpl; | ||
| 10 | import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; | 9 | import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; |
| 11 | import cn.iocoder.yudao.framework.web.config.WebProperties; | 10 | import cn.iocoder.yudao.framework.web.config.WebProperties; |
| 12 | import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; | 11 | import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; |
| @@ -19,7 +18,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | @@ -19,7 +18,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
| 19 | import org.springframework.security.crypto.password.PasswordEncoder; | 18 | import org.springframework.security.crypto.password.PasswordEncoder; |
| 20 | import org.springframework.security.web.AuthenticationEntryPoint; | 19 | import org.springframework.security.web.AuthenticationEntryPoint; |
| 21 | import org.springframework.security.web.access.AccessDeniedHandler; | 20 | import org.springframework.security.web.access.AccessDeniedHandler; |
| 22 | -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; | ||
| 23 | 21 | ||
| 24 | import javax.annotation.Resource; | 22 | import javax.annotation.Resource; |
| 25 | import java.util.List; | 23 | import java.util.List; |
| @@ -64,14 +62,6 @@ public class YudaoSecurityAutoConfiguration { | @@ -64,14 +62,6 @@ public class YudaoSecurityAutoConfiguration { | ||
| 64 | } | 62 | } |
| 65 | 63 | ||
| 66 | /** | 64 | /** |
| 67 | - * 退出处理类 Bean | ||
| 68 | - */ | ||
| 69 | - @Bean | ||
| 70 | - public LogoutSuccessHandler logoutSuccessHandler(MultiUserDetailsAuthenticationProvider authenticationProvider) { | ||
| 71 | - return new LogoutSuccessHandlerImpl(securityProperties, authenticationProvider); | ||
| 72 | - } | ||
| 73 | - | ||
| 74 | - /** | ||
| 75 | * Spring Security 加密器 | 65 | * Spring Security 加密器 |
| 76 | * 考虑到安全性,这里采用 BCryptPasswordEncoder 加密器 | 66 | * 考虑到安全性,这里采用 BCryptPasswordEncoder 加密器 |
| 77 | * | 67 | * |
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
| 1 | package cn.iocoder.yudao.framework.security.config; | 1 | package cn.iocoder.yudao.framework.security.config; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.util.StrUtil; | ||
| 4 | import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider; | 3 | import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider; |
| 5 | import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter; | 4 | import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter; |
| 6 | import cn.iocoder.yudao.framework.web.config.WebProperties; | 5 | import cn.iocoder.yudao.framework.web.config.WebProperties; |
| @@ -17,7 +16,6 @@ import org.springframework.security.config.http.SessionCreationPolicy; | @@ -17,7 +16,6 @@ import org.springframework.security.config.http.SessionCreationPolicy; | ||
| 17 | import org.springframework.security.web.AuthenticationEntryPoint; | 16 | import org.springframework.security.web.AuthenticationEntryPoint; |
| 18 | import org.springframework.security.web.access.AccessDeniedHandler; | 17 | import org.springframework.security.web.access.AccessDeniedHandler; |
| 19 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | 18 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
| 20 | -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; | ||
| 21 | 19 | ||
| 22 | import javax.annotation.Resource; | 20 | import javax.annotation.Resource; |
| 23 | import java.util.List; | 21 | import java.util.List; |
| @@ -47,11 +45,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | @@ -47,11 +45,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | ||
| 47 | @Resource | 45 | @Resource |
| 48 | private AccessDeniedHandler accessDeniedHandler; | 46 | private AccessDeniedHandler accessDeniedHandler; |
| 49 | /** | 47 | /** |
| 50 | - * 退出处理类 Bean | ||
| 51 | - */ | ||
| 52 | - @Resource | ||
| 53 | - private LogoutSuccessHandler logoutSuccessHandler; | ||
| 54 | - /** | ||
| 55 | * Token 认证过滤器 Bean | 48 | * Token 认证过滤器 Bean |
| 56 | */ | 49 | */ |
| 57 | @Resource | 50 | @Resource |
| @@ -114,11 +107,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | @@ -114,11 +107,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | ||
| 114 | .headers().frameOptions().disable().and() | 107 | .headers().frameOptions().disable().and() |
| 115 | // 一堆自定义的 Spring Security 处理器 | 108 | // 一堆自定义的 Spring Security 处理器 |
| 116 | .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) | 109 | .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) |
| 117 | - .accessDeniedHandler(accessDeniedHandler).and() | ||
| 118 | - // 登出地址的配置 | ||
| 119 | - .logout().logoutSuccessHandler(logoutSuccessHandler).logoutRequestMatcher(request -> // 匹配多种用户类型的登出 | ||
| 120 | - StrUtil.equalsAny(request.getRequestURI(), buildAdminApi("/system/logout"), | ||
| 121 | - buildAppApi("/member/logout"))); | 110 | + .accessDeniedHandler(accessDeniedHandler); |
| 111 | + // 登录、登录暂时不使用 Spring Security 的拓展点,主要考虑一方面拓展多用户、多种登录方式相对复杂,一方面用户的学习成本较高 | ||
| 122 | 112 | ||
| 123 | // 设置每个请求的权限 | 113 | // 设置每个请求的权限 |
| 124 | httpSecurity | 114 | httpSecurity |
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java deleted
| 1 | -package cn.iocoder.yudao.framework.security.core.handler; | ||
| 2 | - | ||
| 3 | -import cn.hutool.core.util.StrUtil; | ||
| 4 | -import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | ||
| 6 | -import cn.iocoder.yudao.framework.security.config.SecurityProperties; | ||
| 7 | -import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider; | ||
| 8 | -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | ||
| 9 | -import lombok.AllArgsConstructor; | ||
| 10 | -import org.springframework.security.core.Authentication; | ||
| 11 | -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; | ||
| 12 | - | ||
| 13 | -import javax.servlet.http.HttpServletRequest; | ||
| 14 | -import javax.servlet.http.HttpServletResponse; | ||
| 15 | - | ||
| 16 | - | ||
| 17 | -/** | ||
| 18 | - * 自定义退出处理器 | ||
| 19 | - * | ||
| 20 | - * @author ruoyi | ||
| 21 | - */ | ||
| 22 | -@AllArgsConstructor | ||
| 23 | -public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler { | ||
| 24 | - | ||
| 25 | - private final SecurityProperties securityProperties; | ||
| 26 | - | ||
| 27 | - private final MultiUserDetailsAuthenticationProvider authenticationProvider; | ||
| 28 | - | ||
| 29 | - @Override | ||
| 30 | - public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { | ||
| 31 | - // 执行退出 | ||
| 32 | - String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); | ||
| 33 | - if (StrUtil.isNotBlank(token)) { | ||
| 34 | - authenticationProvider.logout(request, token); | ||
| 35 | - } | ||
| 36 | - // 返回成功 | ||
| 37 | - ServletUtils.writeJSON(response, CommonResult.success(null)); | ||
| 38 | - } | ||
| 39 | - | ||
| 40 | -} |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java
| 1 | package cn.iocoder.yudao.module.member.controller.app.auth; | 1 | package cn.iocoder.yudao.module.member.controller.app.auth; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | +import cn.iocoder.yudao.framework.security.config.SecurityProperties; | ||
| 4 | import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; | 6 | import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; |
| 7 | +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | ||
| 5 | import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; | 8 | import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; |
| 6 | import cn.iocoder.yudao.module.member.service.auth.MemberAuthService; | 9 | import cn.iocoder.yudao.module.member.service.auth.MemberAuthService; |
| 7 | import io.swagger.annotations.Api; | 10 | import io.swagger.annotations.Api; |
| @@ -13,6 +16,7 @@ import org.springframework.validation.annotation.Validated; | @@ -13,6 +16,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 13 | import org.springframework.web.bind.annotation.*; | 16 | import org.springframework.web.bind.annotation.*; |
| 14 | 17 | ||
| 15 | import javax.annotation.Resource; | 18 | import javax.annotation.Resource; |
| 19 | +import javax.servlet.http.HttpServletRequest; | ||
| 16 | import javax.validation.Valid; | 20 | import javax.validation.Valid; |
| 17 | 21 | ||
| 18 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 22 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| @@ -30,6 +34,9 @@ public class AppAuthController { | @@ -30,6 +34,9 @@ public class AppAuthController { | ||
| 30 | @Resource | 34 | @Resource |
| 31 | private MemberAuthService authService; | 35 | private MemberAuthService authService; |
| 32 | 36 | ||
| 37 | + @Resource | ||
| 38 | + private SecurityProperties securityProperties; | ||
| 39 | + | ||
| 33 | @PostMapping("/login") | 40 | @PostMapping("/login") |
| 34 | @ApiOperation("使用手机 + 密码登录") | 41 | @ApiOperation("使用手机 + 密码登录") |
| 35 | public CommonResult<AppAuthLoginRespVO> login(@RequestBody @Valid AppAuthLoginReqVO reqVO) { | 42 | public CommonResult<AppAuthLoginRespVO> login(@RequestBody @Valid AppAuthLoginReqVO reqVO) { |
| @@ -37,6 +44,16 @@ public class AppAuthController { | @@ -37,6 +44,16 @@ public class AppAuthController { | ||
| 37 | return success(AppAuthLoginRespVO.builder().token(token).build()); | 44 | return success(AppAuthLoginRespVO.builder().token(token).build()); |
| 38 | } | 45 | } |
| 39 | 46 | ||
| 47 | + @PostMapping("/logout") | ||
| 48 | + @ApiOperation("登出系统") | ||
| 49 | + public CommonResult<Boolean> logout(HttpServletRequest request) { | ||
| 50 | + String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); | ||
| 51 | + if (StrUtil.isNotBlank(token)) { | ||
| 52 | + authService.logout(token); | ||
| 53 | + } | ||
| 54 | + return success(true); | ||
| 55 | + } | ||
| 56 | + | ||
| 40 | @PostMapping("/sms-login") | 57 | @PostMapping("/sms-login") |
| 41 | @ApiOperation("使用手机 + 验证码登录") | 58 | @ApiOperation("使用手机 + 验证码登录") |
| 42 | public CommonResult<AppAuthLoginRespVO> smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) { | 59 | public CommonResult<AppAuthLoginRespVO> smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) { |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java
0 → 100644
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/config/SecurityConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.member.framework.security.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; | ||
| 4 | +import org.springframework.context.annotation.Bean; | ||
| 5 | +import org.springframework.context.annotation.Configuration; | ||
| 6 | +import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
| 7 | +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * Member 模块的 Security 配置 | ||
| 11 | + */ | ||
| 12 | +@Configuration("memberSecurityConfiguration") | ||
| 13 | +public class SecurityConfiguration { | ||
| 14 | + | ||
| 15 | + @Bean("memberAuthorizeRequestsCustomizer") | ||
| 16 | + public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() { | ||
| 17 | + return new AuthorizeRequestsCustomizer() { | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { | ||
| 21 | + // 登录的接口 | ||
| 22 | + registry.antMatchers(buildAdminApi("/member/auth/logout")).permitAll(); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + }; | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | +} |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/framework/security/core/package-info.java
0 → 100644
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
| 1 | package cn.iocoder.yudao.module.system.controller.admin.auth; | 1 | package cn.iocoder.yudao.module.system.controller.admin.auth; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.SetUtils; |
| 6 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 7 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 8 | +import cn.iocoder.yudao.framework.security.config.SecurityProperties; | ||
| 9 | +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | ||
| 7 | import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; | 10 | import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; |
| 8 | import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; | 11 | import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; |
| 9 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | 12 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; |
| @@ -24,6 +27,7 @@ import org.springframework.validation.annotation.Validated; | @@ -24,6 +27,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 24 | import org.springframework.web.bind.annotation.*; | 27 | import org.springframework.web.bind.annotation.*; |
| 25 | 28 | ||
| 26 | import javax.annotation.Resource; | 29 | import javax.annotation.Resource; |
| 30 | +import javax.servlet.http.HttpServletRequest; | ||
| 27 | import javax.validation.Valid; | 31 | import javax.validation.Valid; |
| 28 | import java.util.List; | 32 | import java.util.List; |
| 29 | import java.util.Set; | 33 | import java.util.Set; |
| @@ -52,15 +56,28 @@ public class AuthController { | @@ -52,15 +56,28 @@ public class AuthController { | ||
| 52 | @Resource | 56 | @Resource |
| 53 | private SocialUserService socialUserService; | 57 | private SocialUserService socialUserService; |
| 54 | 58 | ||
| 59 | + @Resource | ||
| 60 | + private SecurityProperties securityProperties; | ||
| 61 | + | ||
| 55 | @PostMapping("/login") | 62 | @PostMapping("/login") |
| 56 | @ApiOperation("使用账号密码登录") | 63 | @ApiOperation("使用账号密码登录") |
| 57 | @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | 64 | @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 |
| 58 | public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) { | 65 | public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) { |
| 59 | String token = authService.login(reqVO, getClientIP(), getUserAgent()); | 66 | String token = authService.login(reqVO, getClientIP(), getUserAgent()); |
| 60 | - // 返回结果 | ||
| 61 | return success(AuthLoginRespVO.builder().token(token).build()); | 67 | return success(AuthLoginRespVO.builder().token(token).build()); |
| 62 | } | 68 | } |
| 63 | 69 | ||
| 70 | + @PostMapping("/logout") | ||
| 71 | + @ApiOperation("登出系统") | ||
| 72 | + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||
| 73 | + public CommonResult<Boolean> logout(HttpServletRequest request) { | ||
| 74 | + String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); | ||
| 75 | + if (StrUtil.isNotBlank(token)) { | ||
| 76 | + authService.logout(token); | ||
| 77 | + } | ||
| 78 | + return success(true); | ||
| 79 | + } | ||
| 80 | + | ||
| 64 | @GetMapping("/get-permission-info") | 81 | @GetMapping("/get-permission-info") |
| 65 | @ApiOperation("获取登录用户的权限信息") | 82 | @ApiOperation("获取登录用户的权限信息") |
| 66 | public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() { | 83 | public CommonResult<AuthPermissionInfoRespVO> getPermissionInfo() { |
| @@ -130,7 +147,6 @@ public class AuthController { | @@ -130,7 +147,6 @@ public class AuthController { | ||
| 130 | @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | 147 | @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 |
| 131 | public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) { | 148 | public CommonResult<AuthLoginRespVO> socialQuickLogin(@RequestBody @Valid AuthSocialQuickLoginReqVO reqVO) { |
| 132 | String token = authService.socialQuickLogin(reqVO, getClientIP(), getUserAgent()); | 149 | String token = authService.socialQuickLogin(reqVO, getClientIP(), getUserAgent()); |
| 133 | - // 返回结果 | ||
| 134 | return success(AuthLoginRespVO.builder().token(token).build()); | 150 | return success(AuthLoginRespVO.builder().token(token).build()); |
| 135 | } | 151 | } |
| 136 | 152 | ||
| @@ -139,7 +155,6 @@ public class AuthController { | @@ -139,7 +155,6 @@ public class AuthController { | ||
| 139 | @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | 155 | @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 |
| 140 | public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) { | 156 | public CommonResult<AuthLoginRespVO> socialBindLogin(@RequestBody @Valid AuthSocialBindLoginReqVO reqVO) { |
| 141 | String token = authService.socialBindLogin(reqVO, getClientIP(), getUserAgent()); | 157 | String token = authService.socialBindLogin(reqVO, getClientIP(), getUserAgent()); |
| 142 | - // 返回结果 | ||
| 143 | return success(AuthLoginRespVO.builder().token(token).build()); | 158 | return success(AuthLoginRespVO.builder().token(token).build()); |
| 144 | } | 159 | } |
| 145 | 160 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2AccessTokenDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.dataobject.auth; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 5 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | +import lombok.experimental.Accessors; | ||
| 9 | + | ||
| 10 | +import java.util.Date; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * OAuth2 访问令牌 | ||
| 14 | + * | ||
| 15 | + */ | ||
| 16 | +@TableName("system_oauth2_access_token") | ||
| 17 | +@Data | ||
| 18 | +@EqualsAndHashCode(callSuper = true) | ||
| 19 | +@Accessors(chain = true) | ||
| 20 | +public class OAuth2AccessTokenDO extends BaseDO { | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 编号,数据库字典 | ||
| 24 | + */ | ||
| 25 | + private Long id; | ||
| 26 | + /** | ||
| 27 | + * 访问令牌 | ||
| 28 | + */ | ||
| 29 | + private String accessToken; | ||
| 30 | + /** | ||
| 31 | + * 用户编号 | ||
| 32 | + */ | ||
| 33 | + private Long userId; | ||
| 34 | + /** | ||
| 35 | + * 用户类型 | ||
| 36 | + * | ||
| 37 | + * 枚举 {@link UserTypeEnum} | ||
| 38 | + */ | ||
| 39 | + private Integer userType; | ||
| 40 | + /** | ||
| 41 | + * 刷新令牌 | ||
| 42 | + * | ||
| 43 | + * 关联 {@link OAuth2RefreshTokenDO#getRefreshToken()} | ||
| 44 | + */ | ||
| 45 | + private String refreshToken; | ||
| 46 | + /** | ||
| 47 | + * 过期时间 | ||
| 48 | + */ | ||
| 49 | + private Date expiresTime; | ||
| 50 | + /** | ||
| 51 | + * 创建 IP | ||
| 52 | + */ | ||
| 53 | + private String createIp; | ||
| 54 | + | ||
| 55 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2RefreshTokenDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.dal.dataobject.auth; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 5 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | +import lombok.experimental.Accessors; | ||
| 9 | + | ||
| 10 | +import java.util.Date; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * OAuth2 刷新令牌 | ||
| 14 | + * | ||
| 15 | + */ | ||
| 16 | +@TableName("system_oauth2_refresh_token") | ||
| 17 | +@Data | ||
| 18 | +@EqualsAndHashCode(callSuper = true) | ||
| 19 | +@Accessors(chain = true) | ||
| 20 | +public class OAuth2RefreshTokenDO extends BaseDO { | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 编号,数据库字典 | ||
| 24 | + */ | ||
| 25 | + private Long id; | ||
| 26 | + /** | ||
| 27 | + * 刷新令牌 | ||
| 28 | + */ | ||
| 29 | + private String refreshToken; | ||
| 30 | + /** | ||
| 31 | + * 用户编号 | ||
| 32 | + */ | ||
| 33 | + private Integer userId; | ||
| 34 | + /** | ||
| 35 | + * 用户类型 | ||
| 36 | + * | ||
| 37 | + * 枚举 {@link UserTypeEnum} | ||
| 38 | + */ | ||
| 39 | + private Integer userType; | ||
| 40 | + /** | ||
| 41 | + * 过期时间 | ||
| 42 | + */ | ||
| 43 | + private Date expiresTime; | ||
| 44 | + /** | ||
| 45 | + * 创建 IP | ||
| 46 | + */ | ||
| 47 | + private String createIp; | ||
| 48 | + | ||
| 49 | +} |
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 { | @@ -20,6 +20,7 @@ public class SecurityConfiguration { | ||
| 20 | public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { | 20 | public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { |
| 21 | // 登录的接口 | 21 | // 登录的接口 |
| 22 | registry.antMatchers(buildAdminApi("/system/auth/login")).permitAll(); | 22 | registry.antMatchers(buildAdminApi("/system/auth/login")).permitAll(); |
| 23 | + registry.antMatchers(buildAdminApi("/system/auth/logout")).permitAll(); | ||
| 23 | // 社交登陆的接口 | 24 | // 社交登陆的接口 |
| 24 | registry.antMatchers(buildAdminApi("/system/auth/social-auth-redirect")).permitAll(); | 25 | registry.antMatchers(buildAdminApi("/system/auth/social-auth-redirect")).permitAll(); |
| 25 | registry.antMatchers(buildAdminApi("/system/auth/social-quick-login")).permitAll(); | 26 | registry.antMatchers(buildAdminApi("/system/auth/social-quick-login")).permitAll(); |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2Service.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.auth; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * OAuth2.0 Service 接口 | ||
| 5 | + * | ||
| 6 | + * @author 芋道源码 | ||
| 7 | + */ | ||
| 8 | +public interface OAuth2Service { | ||
| 9 | + | ||
| 10 | +// OAuth2AccessTokenDO createAccessToken(Long userId, Integer userType, String createIp); | ||
| 11 | +// | ||
| 12 | +// OAuth2AccessTokenRespDTO checkAccessToken(String accessToken); | ||
| 13 | +// | ||
| 14 | +// OAuth2AccessTokenRespDTO refreshAccessToken(OAuth2RefreshAccessTokenReqDTO refreshAccessTokenDTO); | ||
| 15 | +// | ||
| 16 | +// void removeToken(OAuth2RemoveTokenByUserReqDTO removeTokenDTO); | ||
| 17 | + | ||
| 18 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2ServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.auth; | ||
| 2 | + | ||
| 3 | +import org.springframework.stereotype.Service; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * OAuth2.0 Service 实现类 | ||
| 7 | + * | ||
| 8 | + * @author 芋道源码 | ||
| 9 | + */ | ||
| 10 | +@Service | ||
| 11 | +public class OAuth2ServiceImpl implements OAuth2Service { | ||
| 12 | + | ||
| 13 | +// @Autowired | ||
| 14 | +// private SystemBizProperties systemBizProperties; | ||
| 15 | +// | ||
| 16 | +// @Autowired | ||
| 17 | +// private OAuth2AccessTokenMapper oauth2AccessTokenMapper; | ||
| 18 | +// @Autowired | ||
| 19 | +// private OAuth2RefreshTokenMapper oauth2RefreshTokenMapper; | ||
| 20 | +// | ||
| 21 | +// @Autowired | ||
| 22 | +// private OAuth2AccessTokenRedisDAO oauth2AccessTokenRedisDAO; | ||
| 23 | +// | ||
| 24 | +// @Override | ||
| 25 | +// @Transactional | ||
| 26 | +// public OAuth2AccessTokenRespDTO createAccessToken(OAuth2CreateAccessTokenReqDTO createAccessTokenDTO) { | ||
| 27 | +// // 创建刷新令牌 + 访问令牌 | ||
| 28 | +// OAuth2RefreshTokenDO refreshTokenDO = createOAuth2RefreshToken(createAccessTokenDTO.getUserId(), | ||
| 29 | +// createAccessTokenDTO.getUserType(), createAccessTokenDTO.getCreateIp()); | ||
| 30 | +// OAuth2AccessTokenDO accessTokenDO = createOAuth2AccessToken(refreshTokenDO, createAccessTokenDTO.getCreateIp()); | ||
| 31 | +// // 返回访问令牌 | ||
| 32 | +// return OAuth2Convert.INSTANCE.convert(accessTokenDO); | ||
| 33 | +// } | ||
| 34 | +// | ||
| 35 | +// @Override | ||
| 36 | +// @Transactional | ||
| 37 | +// public OAuth2AccessTokenRespDTO checkAccessToken(String accessToken) { | ||
| 38 | +// OAuth2AccessTokenDO accessTokenDO = this.getOAuth2AccessToken(accessToken); | ||
| 39 | +// if (accessTokenDO == null) { // 不存在 | ||
| 40 | +// throw ServiceExceptionUtil.exception(OAUTH2_ACCESS_TOKEN_NOT_FOUND); | ||
| 41 | +// } | ||
| 42 | +// if (accessTokenDO.getExpiresTime().getTime() < System.currentTimeMillis()) { // 已过期 | ||
| 43 | +// throw ServiceExceptionUtil.exception(OAUTH2_ACCESS_TOKEN_TOKEN_EXPIRED); | ||
| 44 | +// } | ||
| 45 | +// // 返回访问令牌 | ||
| 46 | +// return OAuth2Convert.INSTANCE.convert(accessTokenDO); | ||
| 47 | +// } | ||
| 48 | +// | ||
| 49 | +// @Override | ||
| 50 | +// @Transactional | ||
| 51 | +// public OAuth2AccessTokenRespDTO refreshAccessToken(OAuth2RefreshAccessTokenReqDTO refreshAccessTokenDTO) { | ||
| 52 | +// OAuth2RefreshTokenDO refreshTokenDO = oauth2RefreshTokenMapper.selectById(refreshAccessTokenDTO.getRefreshToken()); | ||
| 53 | +// // 校验刷新令牌是否合法 | ||
| 54 | +// if (refreshTokenDO == null) { // 不存在 | ||
| 55 | +// throw ServiceExceptionUtil.exception(OAUTH2_REFRESH_TOKEN_NOT_FOUND); | ||
| 56 | +// } | ||
| 57 | +// if (refreshTokenDO.getExpiresTime().getTime() < System.currentTimeMillis()) { // 已过期 | ||
| 58 | +// throw ServiceExceptionUtil.exception(OAUTH_REFRESH_TOKEN_EXPIRED); | ||
| 59 | +// } | ||
| 60 | +// | ||
| 61 | +// // 标记 refreshToken 对应的 accessToken 都不合法 | ||
| 62 | +// // 这块的实现,参考了 Spring Security OAuth2 的代码 | ||
| 63 | +// List<OAuth2AccessTokenDO> accessTokenDOs = oauth2AccessTokenMapper.selectListByRefreshToken(refreshAccessTokenDTO.getRefreshToken()); | ||
| 64 | +// accessTokenDOs.forEach(accessTokenDO -> deleteOAuth2AccessToken(accessTokenDO.getId())); | ||
| 65 | +// | ||
| 66 | +// // 创建访问令牌 | ||
| 67 | +// OAuth2AccessTokenDO oauth2AccessTokenDO = createOAuth2AccessToken(refreshTokenDO, refreshAccessTokenDTO.getCreateIp()); | ||
| 68 | +// // 返回访问令牌 | ||
| 69 | +// return OAuth2Convert.INSTANCE.convert(oauth2AccessTokenDO); | ||
| 70 | +// } | ||
| 71 | +// | ||
| 72 | +// @Override | ||
| 73 | +// @Transactional | ||
| 74 | +// public void removeToken(OAuth2RemoveTokenByUserReqDTO removeTokenDTO) { | ||
| 75 | +// // 删除 Access Token | ||
| 76 | +// OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenMapper.selectByUserIdAndUserType( | ||
| 77 | +// removeTokenDTO.getUserId(), removeTokenDTO.getUserType()); | ||
| 78 | +// if (accessTokenDO != null) { | ||
| 79 | +// this.deleteOAuth2AccessToken(accessTokenDO.getId()); | ||
| 80 | +// } | ||
| 81 | +// | ||
| 82 | +// // 删除 Refresh Token | ||
| 83 | +// oauth2RefreshTokenMapper.deleteByUserIdAndUserType(removeTokenDTO.getUserId(), removeTokenDTO.getUserType()); | ||
| 84 | +// } | ||
| 85 | +// | ||
| 86 | +// private OAuth2AccessTokenDO createOAuth2AccessToken(OAuth2RefreshTokenDO refreshTokenDO, String createIp) { | ||
| 87 | +// OAuth2AccessTokenDO accessToken = new OAuth2AccessTokenDO() | ||
| 88 | +// .setId(generateAccessToken()) | ||
| 89 | +// .setUserId(refreshTokenDO.getUserId()).setUserType(refreshTokenDO.getUserType()) | ||
| 90 | +// .setRefreshToken(refreshTokenDO.getId()) | ||
| 91 | +// .setExpiresTime(new Date(System.currentTimeMillis() + systemBizProperties.getAccessTokenExpireTimeMillis())) | ||
| 92 | +// .setCreateIp(createIp); | ||
| 93 | +// oauth2AccessTokenMapper.insert(accessToken); | ||
| 94 | +// return accessToken; | ||
| 95 | +// } | ||
| 96 | +// | ||
| 97 | +// private OAuth2RefreshTokenDO createOAuth2RefreshToken(Integer userId, Integer userType, String createIp) { | ||
| 98 | +// OAuth2RefreshTokenDO refreshToken = new OAuth2RefreshTokenDO() | ||
| 99 | +// .setId(generateRefreshToken()) | ||
| 100 | +// .setUserId(userId).setUserType(userType) | ||
| 101 | +// .setExpiresTime(new Date(System.currentTimeMillis() + systemBizProperties.getRefreshTokenExpireTimeMillis())) | ||
| 102 | +// .setCreateIp(createIp); | ||
| 103 | +// oauth2RefreshTokenMapper.insert(refreshToken); | ||
| 104 | +// return refreshToken; | ||
| 105 | +// } | ||
| 106 | +// | ||
| 107 | +// private OAuth2AccessTokenDO getOAuth2AccessToken(String accessToken) { | ||
| 108 | +// // 优先从 Redis 中获取 | ||
| 109 | +// OAuth2AccessTokenDO accessTokenDO = oauth2AccessTokenRedisDAO.get(accessToken); | ||
| 110 | +// if (accessTokenDO != null) { | ||
| 111 | +// return accessTokenDO; | ||
| 112 | +// } | ||
| 113 | +// | ||
| 114 | +// // 获取不到,从 MySQL 中获取 | ||
| 115 | +// accessTokenDO = oauth2AccessTokenMapper.selectById(accessToken); | ||
| 116 | +// // 如果在 MySQL 存在,则往 Redis 中写入 | ||
| 117 | +// if (accessTokenDO != null) { | ||
| 118 | +// oauth2AccessTokenRedisDAO.set(accessTokenDO); | ||
| 119 | +// } | ||
| 120 | +// return accessTokenDO; | ||
| 121 | +// } | ||
| 122 | +// | ||
| 123 | +// /** | ||
| 124 | +// * 删除 accessToken 的 MySQL 与 Redis 的数据 | ||
| 125 | +// * | ||
| 126 | +// * @param accessToken 访问令牌 | ||
| 127 | +// */ | ||
| 128 | +// private void deleteOAuth2AccessToken(String accessToken) { | ||
| 129 | +// // 删除 MySQL | ||
| 130 | +// oauth2AccessTokenMapper.deleteById(accessToken); | ||
| 131 | +// // 删除 Redis | ||
| 132 | +// oauth2AccessTokenRedisDAO.delete(accessToken); | ||
| 133 | +// } | ||
| 134 | +// | ||
| 135 | +// private static String generateAccessToken() { | ||
| 136 | +// return StringUtils.uuid(true); | ||
| 137 | +// } | ||
| 138 | +// | ||
| 139 | +// private static String generateRefreshToken() { | ||
| 140 | +// return StringUtils.uuid(true); | ||
| 141 | +// } | ||
| 142 | + | ||
| 143 | +} |
yudao-ui-admin/src/api/login.js
| @@ -26,7 +26,7 @@ export function getInfo() { | @@ -26,7 +26,7 @@ export function getInfo() { | ||
| 26 | // 退出方法 | 26 | // 退出方法 |
| 27 | export function logout() { | 27 | export function logout() { |
| 28 | return request({ | 28 | return request({ |
| 29 | - url: '/system/logout', | 29 | + url: '/system/auth/logout', |
| 30 | method: 'post' | 30 | method: 'post' |
| 31 | }) | 31 | }) |
| 32 | } | 32 | } |