Commit a56b4a7c9c6b1d4363a65dd87c1c2fd112d25d75
1 parent
23888c5a
增加三方登陆的 redirect uri
Showing
22 changed files
with
258 additions
and
840 deletions
yudao-admin-server/pom.xml
| @@ -117,6 +117,12 @@ | @@ -117,6 +117,12 @@ | ||
| 117 | <artifactId>screw-core</artifactId> <!-- 实现数据库文档 --> | 117 | <artifactId>screw-core</artifactId> <!-- 实现数据库文档 --> |
| 118 | </dependency> | 118 | </dependency> |
| 119 | 119 | ||
| 120 | + <!-- TODO 后续看情况,进行调整 --> | ||
| 121 | + <dependency> | ||
| 122 | + <groupId>com.xkcoding.justauth</groupId> | ||
| 123 | + <artifactId>justauth-spring-boot-starter</artifactId> | ||
| 124 | + <version>1.4.0</version> | ||
| 125 | + </dependency> | ||
| 120 | </dependencies> | 126 | </dependencies> |
| 121 | 127 | ||
| 122 | <build> | 128 | <build> |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/controller/file/InfFileController.java
| @@ -41,7 +41,7 @@ public class InfFileController { | @@ -41,7 +41,7 @@ public class InfFileController { | ||
| 41 | @ApiOperation("上传文件") | 41 | @ApiOperation("上传文件") |
| 42 | @ApiImplicitParams({ | 42 | @ApiImplicitParams({ |
| 43 | @ApiImplicitParam(name = "file", value = "文件附件", required = true, dataTypeClass = MultipartFile.class), | 43 | @ApiImplicitParam(name = "file", value = "文件附件", required = true, dataTypeClass = MultipartFile.class), |
| 44 | - @ApiImplicitParam(name = "path", value = "文件路径", required = false, example = "yudaoyuanma.png", dataTypeClass = String.class) | 44 | + @ApiImplicitParam(name = "path", value = "文件路径", example = "yudaoyuanma.png", dataTypeClass = String.class) |
| 45 | }) | 45 | }) |
| 46 | public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file, | 46 | public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file, |
| 47 | @RequestParam("path") String path) throws IOException { | 47 | @RequestParam("path") String path) throws IOException { |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java
| 1 | package cn.iocoder.yudao.adminserver.modules.system.controller.auth; | 1 | package cn.iocoder.yudao.adminserver.modules.system.controller.auth; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.net.url.UrlBuilder; | ||
| 4 | +import cn.hutool.http.HttpUtil; | ||
| 5 | +import cn.hutool.json.JSONUtil; | ||
| 6 | +import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum; | ||
| 3 | import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; | 7 | import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; |
| 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 8 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 9 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 10 | +import cn.iocoder.yudao.framework.common.util.http.HttpUtils; | ||
| 6 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 11 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 7 | import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; | 12 | import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginReqVO; |
| 8 | import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginRespVO; | 13 | import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginRespVO; |
| @@ -18,15 +23,31 @@ import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermiss | @@ -18,15 +23,31 @@ import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermiss | ||
| 18 | import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; | 23 | import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; |
| 19 | import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; | 24 | import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; |
| 20 | import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | 25 | import cn.iocoder.yudao.framework.common.util.collection.SetUtils; |
| 26 | +import com.aliyuncs.CommonResponse; | ||
| 27 | +import com.xkcoding.justauth.AuthRequestFactory; | ||
| 21 | import io.swagger.annotations.Api; | 28 | import io.swagger.annotations.Api; |
| 29 | +import io.swagger.annotations.ApiImplicitParam; | ||
| 30 | +import io.swagger.annotations.ApiImplicitParams; | ||
| 22 | import io.swagger.annotations.ApiOperation; | 31 | import io.swagger.annotations.ApiOperation; |
| 23 | -import org.springframework.security.core.Authentication; | ||
| 24 | -import org.springframework.security.core.context.SecurityContextHolder; | 32 | +import lombok.extern.slf4j.Slf4j; |
| 33 | +import me.zhyd.oauth.model.AuthCallback; | ||
| 34 | +import me.zhyd.oauth.model.AuthResponse; | ||
| 35 | +import me.zhyd.oauth.model.AuthUser; | ||
| 36 | +import me.zhyd.oauth.request.AuthRequest; | ||
| 37 | +import me.zhyd.oauth.utils.AuthStateUtils; | ||
| 38 | +import org.apache.commons.lang.StringUtils; | ||
| 39 | +import org.quartz.SimpleTrigger; | ||
| 25 | import org.springframework.validation.annotation.Validated; | 40 | import org.springframework.validation.annotation.Validated; |
| 26 | import org.springframework.web.bind.annotation.*; | 41 | import org.springframework.web.bind.annotation.*; |
| 42 | +import org.springframework.web.multipart.MultipartFile; | ||
| 43 | +import org.springframework.web.util.UriBuilder; | ||
| 27 | 44 | ||
| 28 | import javax.annotation.Resource; | 45 | import javax.annotation.Resource; |
| 46 | +import javax.servlet.http.HttpServletResponse; | ||
| 29 | import javax.validation.Valid; | 47 | import javax.validation.Valid; |
| 48 | +import java.io.IOException; | ||
| 49 | +import java.net.URL; | ||
| 50 | +import java.nio.charset.Charset; | ||
| 30 | import java.util.List; | 51 | import java.util.List; |
| 31 | 52 | ||
| 32 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 53 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| @@ -39,6 +60,7 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUse | @@ -39,6 +60,7 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUse | ||
| 39 | @RestController | 60 | @RestController |
| 40 | @RequestMapping("/") | 61 | @RequestMapping("/") |
| 41 | @Validated | 62 | @Validated |
| 63 | +@Slf4j | ||
| 42 | public class SysAuthController { | 64 | public class SysAuthController { |
| 43 | 65 | ||
| 44 | @Resource | 66 | @Resource |
| @@ -52,6 +74,9 @@ public class SysAuthController { | @@ -52,6 +74,9 @@ public class SysAuthController { | ||
| 52 | @Resource | 74 | @Resource |
| 53 | private SysUserSessionService sysUserSessionService; | 75 | private SysUserSessionService sysUserSessionService; |
| 54 | 76 | ||
| 77 | + @Resource | ||
| 78 | + private AuthRequestFactory authRequestFactory; | ||
| 79 | + | ||
| 55 | @PostMapping("/login") | 80 | @PostMapping("/login") |
| 56 | @ApiOperation("使用账号密码登录") | 81 | @ApiOperation("使用账号密码登录") |
| 57 | @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | 82 | @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 |
| @@ -61,17 +86,42 @@ public class SysAuthController { | @@ -61,17 +86,42 @@ public class SysAuthController { | ||
| 61 | return success(SysAuthLoginRespVO.builder().token(token).build()); | 86 | return success(SysAuthLoginRespVO.builder().token(token).build()); |
| 62 | } | 87 | } |
| 63 | 88 | ||
| 64 | - @RequestMapping("/auth2/login/{oauthType}") | ||
| 65 | - @ApiOperation("第三方登录") | ||
| 66 | - @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||
| 67 | - public CommonResult<SysAuthLoginRespVO> login(@PathVariable String oauthType) { | ||
| 68 | - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||
| 69 | - //TODO NPE | ||
| 70 | - String token = sysUserSessionService.getSessionId(authentication.getName()); | ||
| 71 | - // 返回结果 | ||
| 72 | - return success(SysAuthLoginRespVO.builder().token(token).build()); | 89 | + @GetMapping("/third-login-redirect") |
| 90 | + @ApiOperation("三方登陆的跳转") | ||
| 91 | + @ApiImplicitParams({ | ||
| 92 | + @ApiImplicitParam(name = "type", value = "三方类型", required = true, dataTypeClass = Integer.class), | ||
| 93 | + @ApiImplicitParam(name = "redirectUri", value = "回调路径", dataTypeClass = String.class) | ||
| 94 | + }) | ||
| 95 | + public CommonResult<String> login(@RequestParam("type") Integer type, | ||
| 96 | + @RequestParam("redirectUri") String redirectUri) throws IOException { | ||
| 97 | + // 获得对应的 AuthRequest 实现 | ||
| 98 | + AuthRequest authRequest = authRequestFactory.get(SysUserSocialTypeEnum.valueOfType(type).getSource()); | ||
| 99 | + // 生成跳转地址 | ||
| 100 | + String authorizeUri = authRequest.authorize(AuthStateUtils.createState()); | ||
| 101 | + authorizeUri = HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri); | ||
| 102 | +// authorizeUri = UrlBuilder.fromBaseUrl(authorizeUri).queryParam("redirect_uri", redirectUri).build(); | ||
| 103 | + return CommonResult.success(authorizeUri); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + @RequestMapping("/{type}/callback") | ||
| 107 | + public AuthResponse login(@PathVariable String type, AuthCallback callback) { | ||
| 108 | + AuthRequest authRequest = authRequestFactory.get(type); | ||
| 109 | + AuthResponse<AuthUser> response = authRequest.login(callback); | ||
| 110 | + log.info("【response】= {}", JSONUtil.toJsonStr(response)); | ||
| 111 | + return response; | ||
| 73 | } | 112 | } |
| 74 | 113 | ||
| 114 | +// @RequestMapping("/auth2/login/{oauthType}") | ||
| 115 | +// @ApiOperation("第三方登录") | ||
| 116 | +// @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||
| 117 | +// public CommonResult<SysAuthLoginRespVO> login(@PathVariable String oauthType) { | ||
| 118 | +// Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||
| 119 | +// //TODO NPE | ||
| 120 | +// String token = sysUserSessionService.getSessionId(authentication.getName()); | ||
| 121 | +// // 返回结果 | ||
| 122 | +// return success(SysAuthLoginRespVO.builder().token(token).build()); | ||
| 123 | +// } | ||
| 124 | + | ||
| 75 | @GetMapping("/get-permission-info") | 125 | @GetMapping("/get-permission-info") |
| 76 | @ApiOperation("获取登陆用户的权限信息") | 126 | @ApiOperation("获取登陆用户的权限信息") |
| 77 | public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() { | 127 | public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() { |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java
| 1 | package cn.iocoder.yudao.adminserver.modules.system.convert.auth; | 1 | package cn.iocoder.yudao.adminserver.modules.system.convert.auth; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserCreateReqVO; | ||
| 4 | -import cn.iocoder.yudao.adminserver.modules.system.enums.common.SysSexEnum; | ||
| 5 | -import cn.iocoder.yudao.framework.security.core.Auth2LoginUser; | ||
| 6 | -import cn.iocoder.yudao.framework.security.core.LoginUser; | ||
| 7 | import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO; | 3 | import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO; |
| 8 | import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO; | 4 | import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO; |
| 9 | import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; | 5 | import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdatePasswordReqVO; |
| 10 | import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; | 6 | import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.profile.SysUserProfileUpdateReqVO; |
| 7 | +import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserCreateReqVO; | ||
| 11 | import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; | 8 | import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO; |
| 12 | import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; | 9 | import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; |
| 13 | import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; | 10 | import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; |
| 14 | import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum; | 11 | import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum; |
| 15 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 12 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 16 | -import me.zhyd.oauth.enums.AuthUserGender; | 13 | +import cn.iocoder.yudao.framework.security.core.LoginUser; |
| 17 | import me.zhyd.oauth.model.AuthUser; | 14 | import me.zhyd.oauth.model.AuthUser; |
| 18 | -import org.mapstruct.*; | 15 | +import org.mapstruct.Mapper; |
| 16 | +import org.mapstruct.Mapping; | ||
| 17 | +import org.mapstruct.Mappings; | ||
| 19 | import org.mapstruct.factory.Mappers; | 18 | import org.mapstruct.factory.Mappers; |
| 20 | import org.slf4j.LoggerFactory; | 19 | import org.slf4j.LoggerFactory; |
| 21 | 20 | ||
| 22 | -import java.util.ArrayList; | ||
| 23 | -import java.util.Comparator; | ||
| 24 | -import java.util.LinkedHashMap; | ||
| 25 | -import java.util.List; | ||
| 26 | -import java.util.Map; | 21 | +import java.util.*; |
| 27 | 22 | ||
| 28 | -@Mapper(uses = SysAuthConvert.UserSexTransform.class) | 23 | +@Mapper |
| 29 | public interface SysAuthConvert { | 24 | public interface SysAuthConvert { |
| 30 | 25 | ||
| 31 | SysAuthConvert INSTANCE = Mappers.getMapper(SysAuthConvert.class); | 26 | SysAuthConvert INSTANCE = Mappers.getMapper(SysAuthConvert.class); |
| @@ -33,7 +28,6 @@ public interface SysAuthConvert { | @@ -33,7 +28,6 @@ public interface SysAuthConvert { | ||
| 33 | @Mapping(source = "updateTime", target = "updateTime", ignore = true) | 28 | @Mapping(source = "updateTime", target = "updateTime", ignore = true) |
| 34 | // 字段相同,但是含义不同,忽略 | 29 | // 字段相同,但是含义不同,忽略 |
| 35 | LoginUser convert(SysUserDO bean); | 30 | LoginUser convert(SysUserDO bean); |
| 36 | - Auth2LoginUser getAuth2LoginUser(SysUserDO bean); | ||
| 37 | 31 | ||
| 38 | default SysAuthPermissionInfoRespVO convert(SysUserDO user, List<SysRoleDO> roleList, List<SysMenuDO> menuList) { | 32 | default SysAuthPermissionInfoRespVO convert(SysUserDO user, List<SysRoleDO> roleList, List<SysMenuDO> menuList) { |
| 39 | return SysAuthPermissionInfoRespVO.builder() | 33 | return SysAuthPermissionInfoRespVO.builder() |
| @@ -49,16 +43,6 @@ public interface SysAuthConvert { | @@ -49,16 +43,6 @@ public interface SysAuthConvert { | ||
| 49 | 43 | ||
| 50 | LoginUser convert(SysUserProfileUpdatePasswordReqVO reqVO); | 44 | LoginUser convert(SysUserProfileUpdatePasswordReqVO reqVO); |
| 51 | 45 | ||
| 52 | - @Mappings( | ||
| 53 | - @Mapping(target = "sex", source = "gender") | ||
| 54 | - ) | ||
| 55 | - SysUserCreateReqVO convert(AuthUser authUser); | ||
| 56 | - | ||
| 57 | - @Mappings( | ||
| 58 | - @Mapping(target = "thirdPartyUserId", source = "uuid") | ||
| 59 | - ) | ||
| 60 | - Auth2LoginUser getLoginUser(AuthUser authUser); | ||
| 61 | - | ||
| 62 | /** | 46 | /** |
| 63 | * 将菜单列表,构建成菜单树 | 47 | * 将菜单列表,构建成菜单树 |
| 64 | * | 48 | * |
| @@ -91,24 +75,4 @@ public interface SysAuthConvert { | @@ -91,24 +75,4 @@ public interface SysAuthConvert { | ||
| 91 | return CollectionUtils.filterList(treeNodeMap.values(), node -> MenuIdEnum.ROOT.getId().equals(node.getParentId())); | 75 | return CollectionUtils.filterList(treeNodeMap.values(), node -> MenuIdEnum.ROOT.getId().equals(node.getParentId())); |
| 92 | } | 76 | } |
| 93 | 77 | ||
| 94 | - public class UserSexTransform { | ||
| 95 | - | ||
| 96 | - public int toInt (AuthUserGender gender){ | ||
| 97 | - switch (gender) { | ||
| 98 | - case MALE: | ||
| 99 | - return SysSexEnum.MALE.getSex(); | ||
| 100 | - case FEMALE: | ||
| 101 | - return SysSexEnum.FEMALE.getSex(); | ||
| 102 | - default: | ||
| 103 | - return SysSexEnum.UNKNOWN.getSex(); | ||
| 104 | - } | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | - public AuthUserGender strToBoolean(int sex){ | ||
| 108 | - if(sex == SysSexEnum.UNKNOWN.getSex()) { | ||
| 109 | - return AuthUserGender.UNKNOWN; | ||
| 110 | - } | ||
| 111 | - return AuthUserGender.getRealGender(String.valueOf(sex)); | ||
| 112 | - } | ||
| 113 | - } | ||
| 114 | } | 78 | } |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/config/AuthConfig.java deleted
| 1 | -package cn.iocoder.yudao.adminserver.modules.system.convert.auth.config; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.adminserver.modules.system.convert.auth.handler.DefaultSignUpUrlAuthenticationSuccessHandler; | ||
| 4 | -import cn.iocoder.yudao.framework.security.core.handler.AbstractSignUpUrlAuthenticationSuccessHandler; | ||
| 5 | -import org.springframework.context.annotation.Bean; | ||
| 6 | -import org.springframework.context.annotation.Configuration; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * @author weir | ||
| 10 | - */ | ||
| 11 | -@Configuration | ||
| 12 | -public class AuthConfig { | ||
| 13 | - @Bean | ||
| 14 | - public AbstractSignUpUrlAuthenticationSuccessHandler authenticationSuccessHandler() { | ||
| 15 | - AbstractSignUpUrlAuthenticationSuccessHandler successHandler = new DefaultSignUpUrlAuthenticationSuccessHandler(); | ||
| 16 | - successHandler.setDefaultTargetUrl("/api/callback"); | ||
| 17 | - return successHandler; | ||
| 18 | - } | ||
| 19 | -} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/handler/DefaultSignUpUrlAuthenticationSuccessHandler.java deleted
| 1 | -/* | ||
| 2 | - * MIT License | ||
| 3 | - * Copyright (c) 2020-2029 YongWu zheng (dcenter.top and gitee.com/pcore and github.com/ZeroOrInfinity) | ||
| 4 | - * | ||
| 5 | - * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | - * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | - * in the Software without restriction, including without limitation the rights | ||
| 8 | - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | - * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | - * furnished to do so, subject to the following conditions: | ||
| 11 | - * | ||
| 12 | - * The above copyright notice and this permission notice shall be included in all | ||
| 13 | - * copies or substantial portions of the Software. | ||
| 14 | - * | ||
| 15 | - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | - * SOFTWARE. | ||
| 22 | - */ | ||
| 23 | -package cn.iocoder.yudao.adminserver.modules.system.convert.auth.handler; | ||
| 24 | - | ||
| 25 | -import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginRespVO; | ||
| 26 | -import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; | ||
| 27 | -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; | ||
| 28 | -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 29 | -import cn.iocoder.yudao.framework.security.core.Auth2LoginUser; | ||
| 30 | -import cn.iocoder.yudao.framework.security.core.LoginUser; | ||
| 31 | -import cn.iocoder.yudao.framework.security.core.handler.AbstractSignUpUrlAuthenticationSuccessHandler; | ||
| 32 | -import org.apache.commons.lang3.StringUtils; | ||
| 33 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 34 | -import org.springframework.http.HttpStatus; | ||
| 35 | -import org.springframework.security.core.Authentication; | ||
| 36 | -import org.springframework.security.core.context.SecurityContextHolder; | ||
| 37 | -import org.springframework.security.web.DefaultRedirectStrategy; | ||
| 38 | -import org.springframework.security.web.savedrequest.HttpSessionRequestCache; | ||
| 39 | -import org.springframework.security.web.savedrequest.RequestCache; | ||
| 40 | - | ||
| 41 | -import javax.annotation.Resource; | ||
| 42 | -import javax.servlet.ServletException; | ||
| 43 | -import javax.servlet.http.HttpServletRequest; | ||
| 44 | -import javax.servlet.http.HttpServletResponse; | ||
| 45 | -import java.io.IOException; | ||
| 46 | -import java.util.Set; | ||
| 47 | - | ||
| 48 | -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 49 | -import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; | ||
| 50 | -import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent; | ||
| 51 | -import static java.util.Collections.singleton; | ||
| 52 | -import static top.dcenter.ums.security.core.oauth.util.MvcUtil.*; | ||
| 53 | - | ||
| 54 | -/** | ||
| 55 | - * @author weir | ||
| 56 | - */ | ||
| 57 | -public class DefaultSignUpUrlAuthenticationSuccessHandler extends AbstractSignUpUrlAuthenticationSuccessHandler { | ||
| 58 | - private RequestCache requestCache = new HttpSessionRequestCache(); | ||
| 59 | - @Autowired | ||
| 60 | - private SysUserSessionService userSessionService; | ||
| 61 | - @Resource | ||
| 62 | - private SysPermissionService permissionService; | ||
| 63 | - | ||
| 64 | - @Override | ||
| 65 | - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { | ||
| 66 | - final Object principal = authentication.getPrincipal(); | ||
| 67 | - String token = userSessionService.createUserSession(defaultHandleUserRoles((LoginUser) principal), getClientIP(), getUserAgent()); | ||
| 68 | - if(StringUtils.isNotBlank(token)) { | ||
| 69 | - SecurityContextHolder.getContext().setAuthentication(authentication); | ||
| 70 | - } | ||
| 71 | - if (principal instanceof Auth2LoginUser) { | ||
| 72 | - new DefaultRedirectStrategy().sendRedirect(request, response, getUrl() + token); | ||
| 73 | - return; | ||
| 74 | - } | ||
| 75 | - if (isAjaxOrJson(request)) { | ||
| 76 | - responseWithJson(response, HttpStatus.OK.value(), toJsonString(success(SysAuthLoginRespVO.builder().token(token).build()))); | ||
| 77 | - return; | ||
| 78 | - } | ||
| 79 | - try { | ||
| 80 | - requestCache.saveRequest(request, response); | ||
| 81 | - super.setRequestCache(requestCache); | ||
| 82 | - super.onAuthenticationSuccess(request, response, authentication); | ||
| 83 | - } catch (ServletException e) { | ||
| 84 | - e.printStackTrace(); | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - } | ||
| 88 | - | ||
| 89 | - private String getUrl() { | ||
| 90 | -// return "http://localhost/oauthLogin/gitee?token="; | ||
| 91 | - return "http://127.0.0.1:1024/oauthLogin/gitee?token="; | ||
| 92 | - } | ||
| 93 | - | ||
| 94 | - /** | ||
| 95 | - * 默认处理方式处理用户角色列表;建议角色权限前置到 UserDetails | ||
| 96 | - * | ||
| 97 | - * @param loginUser 用户 | ||
| 98 | - * @return | ||
| 99 | - */ | ||
| 100 | - private LoginUser defaultHandleUserRoles(LoginUser loginUser) { | ||
| 101 | - Set<Long> roleIds = loginUser.getRoleIds(); | ||
| 102 | - if (roleIds == null || roleIds.isEmpty()) { | ||
| 103 | - Set<Long> userRoleIds = permissionService.getUserRoleIds(loginUser.getId(), singleton(CommonStatusEnum.ENABLE.getStatus())); | ||
| 104 | - loginUser.setRoleIds(userRoleIds); | ||
| 105 | - } | ||
| 106 | - return loginUser; | ||
| 107 | - } | ||
| 108 | - | ||
| 109 | - @Override | ||
| 110 | - public void setRequestCache(RequestCache requestCache) { | ||
| 111 | - this.requestCache = requestCache; | ||
| 112 | - } | ||
| 113 | -} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SocialUserDO.java deleted
| 1 | -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social; | ||
| 2 | - | ||
| 3 | -import com.baomidou.mybatisplus.annotation.TableName; | ||
| 4 | -import lombok.Data; | ||
| 5 | -import me.zhyd.oauth.model.AuthUser; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * @author weir | ||
| 9 | - */ | ||
| 10 | -@Data | ||
| 11 | -@TableName("user_connection") | ||
| 12 | -public class SocialUserDO extends AuthUser { | ||
| 13 | -} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SysUserSocialDO.java deleted
| 1 | -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | -import com.baomidou.mybatisplus.annotation.TableId; | ||
| 5 | -import com.baomidou.mybatisplus.annotation.TableName; | ||
| 6 | -import lombok.Data; | ||
| 7 | -import lombok.EqualsAndHashCode; | ||
| 8 | - | ||
| 9 | -/** | ||
| 10 | - * 系统用户和第三方用户关联表 | ||
| 11 | - * @author weir | ||
| 12 | - */ | ||
| 13 | -@TableName("sys_user_social") | ||
| 14 | -@Data | ||
| 15 | -public class SysUserSocialDO extends BaseDO { | ||
| 16 | - /** | ||
| 17 | - * 自增主键 | ||
| 18 | - */ | ||
| 19 | - @TableId | ||
| 20 | - private Long id; | ||
| 21 | - /** | ||
| 22 | - * 用户 ID | ||
| 23 | - */ | ||
| 24 | - private Long userId; | ||
| 25 | - /** | ||
| 26 | - * 角色 ID | ||
| 27 | - */ | ||
| 28 | - private String socialUserId; | ||
| 29 | -} | ||
| 30 | - | ||
| 31 | - |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/user/SysUserSocialDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | ||
| 6 | +import com.baomidou.mybatisplus.annotation.TableId; | ||
| 7 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 8 | +import lombok.*; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 三方登陆信息 | ||
| 12 | + * 通过 {@link SysUserSocialDO#getUserId()} 关联到对应的 {@link SysUserDO} | ||
| 13 | + * | ||
| 14 | + * @author weir | ||
| 15 | + */ | ||
| 16 | +@TableName(value = "sys_user_social", autoResultMap = true) | ||
| 17 | +@Data | ||
| 18 | +@EqualsAndHashCode(callSuper = true) | ||
| 19 | +@Builder | ||
| 20 | +@NoArgsConstructor | ||
| 21 | +@AllArgsConstructor | ||
| 22 | +public class SysUserSocialDO extends BaseDO { | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 自增主键 | ||
| 26 | + */ | ||
| 27 | + @TableId | ||
| 28 | + private Long id; | ||
| 29 | + /** | ||
| 30 | + * 用户编号 | ||
| 31 | + */ | ||
| 32 | + private Long userId; | ||
| 33 | + /** | ||
| 34 | + * 用户类型 | ||
| 35 | + * | ||
| 36 | + * 枚举 {@link UserTypeEnum} | ||
| 37 | + */ | ||
| 38 | + private Integer userType; | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 三方平台的类型 | ||
| 42 | + */ | ||
| 43 | + private SysUserSocialTypeEnum type; | ||
| 44 | + /** | ||
| 45 | + * 三方 openid | ||
| 46 | + */ | ||
| 47 | + private String openid; | ||
| 48 | + /** | ||
| 49 | + * 三方 token | ||
| 50 | + */ | ||
| 51 | + private String token; | ||
| 52 | + /** | ||
| 53 | + * 三方的全局编号 | ||
| 54 | + * | ||
| 55 | + * 例如说,微信平台的 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/union-id.html | ||
| 56 | + * 如果没有 unionId 的平台,直接使用 openid 作为该字段的值 | ||
| 57 | + */ | ||
| 58 | + private String unionId; | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * 用户昵称 | ||
| 62 | + */ | ||
| 63 | + private String nickname; | ||
| 64 | + /** | ||
| 65 | + * 用户头像 | ||
| 66 | + */ | ||
| 67 | + private String avatar; | ||
| 68 | + /** | ||
| 69 | + * 原始数据,一般是 JSON 格式 | ||
| 70 | + */ | ||
| 71 | + private String info; | ||
| 72 | + | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | + |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysSysUserSocialMapper.java
| 1 | package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social; | 1 | package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysUserSocialDO; | 3 | +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserSocialDO; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import org.apache.ibatis.annotations.Mapper; | 5 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 6 |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysUserSocialMapper.java
| 1 | package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social; | 1 | package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysUserSocialDO; | 3 | +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserSocialDO; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import org.apache.ibatis.annotations.Mapper; | 5 | import org.apache.ibatis.annotations.Mapper; |
| 6 | 6 |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/user/SysUserSocialTypeEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.system.enums.user; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ArrayUtil; | ||
| 4 | +import cn.iocoder.yudao.adminserver.modules.system.enums.errorcode.SysErrorCodeTypeEnum; | ||
| 5 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | ||
| 6 | +import jodd.util.ArraysUtil; | ||
| 7 | +import lombok.AllArgsConstructor; | ||
| 8 | +import lombok.Getter; | ||
| 9 | + | ||
| 10 | +import java.util.Arrays; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 用户的三方平台的类型枚举 | ||
| 14 | + * | ||
| 15 | + * @author 芋道源码 | ||
| 16 | + */ | ||
| 17 | +@Getter | ||
| 18 | +@AllArgsConstructor | ||
| 19 | +public enum SysUserSocialTypeEnum implements IntArrayValuable { | ||
| 20 | + | ||
| 21 | + GITEE(10, "GITEE"), // https://gitee.com/api/v5/oauth_doc#/ | ||
| 22 | + ; | ||
| 23 | + | ||
| 24 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysUserSocialTypeEnum::getType).toArray(); | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 类型 | ||
| 28 | + */ | ||
| 29 | + private final Integer type; | ||
| 30 | + /** | ||
| 31 | + * 类型的标识 | ||
| 32 | + */ | ||
| 33 | + private final String source; | ||
| 34 | + | ||
| 35 | + @Override | ||
| 36 | + public int[] array() { | ||
| 37 | + return ARRAYS; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + public static SysUserSocialTypeEnum valueOfType(Integer type) { | ||
| 41 | + return ArrayUtil.firstMatch(o -> o.getType().equals(type), values()); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | +} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/UserDetailsServiceImpl.java deleted
| 1 | -/* | ||
| 2 | - * MIT License | ||
| 3 | - * Copyright (c) 2020-2029 YongWu zheng (dcenter.top and gitee.com/pcore and github.com/ZeroOrInfinity) | ||
| 4 | - * | ||
| 5 | - * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | - * of this software and associated documentation files (the "Software"), to deal | ||
| 7 | - * in the Software without restriction, including without limitation the rights | ||
| 8 | - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | - * copies of the Software, and to permit persons to whom the Software is | ||
| 10 | - * furnished to do so, subject to the following conditions: | ||
| 11 | - * | ||
| 12 | - * The above copyright notice and this permission notice shall be included in all | ||
| 13 | - * copies or substantial portions of the Software. | ||
| 14 | - * | ||
| 15 | - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | - * SOFTWARE. | ||
| 22 | - */ | ||
| 23 | - | ||
| 24 | -package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl; | ||
| 25 | - | ||
| 26 | -import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserCreateReqVO; | ||
| 27 | -import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert; | ||
| 28 | -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; | ||
| 29 | -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; | ||
| 30 | -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; | ||
| 31 | -import cn.iocoder.yudao.framework.security.core.Auth2LoginUser; | ||
| 32 | -import cn.iocoder.yudao.framework.security.core.LoginUser; | ||
| 33 | -import com.google.common.collect.Sets; | ||
| 34 | -import me.zhyd.oauth.model.AuthUser; | ||
| 35 | -import org.apache.commons.lang3.StringUtils; | ||
| 36 | -import org.slf4j.Logger; | ||
| 37 | -import org.slf4j.LoggerFactory; | ||
| 38 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 39 | -import org.springframework.lang.NonNull; | ||
| 40 | -import org.springframework.security.core.authority.AuthorityUtils; | ||
| 41 | -import org.springframework.security.core.userdetails.User; | ||
| 42 | -import org.springframework.security.core.userdetails.UserCache; | ||
| 43 | -import org.springframework.security.core.userdetails.UserDetails; | ||
| 44 | -import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||
| 45 | -import org.springframework.security.crypto.password.PasswordEncoder; | ||
| 46 | -import org.springframework.stereotype.Service; | ||
| 47 | -import org.springframework.web.context.request.RequestAttributes; | ||
| 48 | -import org.springframework.web.context.request.RequestContextHolder; | ||
| 49 | -import top.dcenter.ums.security.core.oauth.enums.ErrorCodeEnum; | ||
| 50 | -import top.dcenter.ums.security.core.oauth.exception.RegisterUserFailureException; | ||
| 51 | -import top.dcenter.ums.security.core.oauth.exception.UserNotExistException; | ||
| 52 | -import top.dcenter.ums.security.core.oauth.service.UmsUserDetailsService; | ||
| 53 | - | ||
| 54 | -import javax.annotation.Resource; | ||
| 55 | -import java.util.ArrayList; | ||
| 56 | -import java.util.List; | ||
| 57 | -import java.util.Map; | ||
| 58 | -import java.util.Set; | ||
| 59 | - | ||
| 60 | -/** | ||
| 61 | - * 用户密码与手机短信登录与注册服务:<br><br> | ||
| 62 | - * 1. 用于第三方登录与手机短信登录逻辑。<br><br> | ||
| 63 | - * 2. 用于用户密码登录逻辑。<br><br> | ||
| 64 | - * 3. 用户注册逻辑。<br><br> | ||
| 65 | - * @author YongWu zheng | ||
| 66 | - * @version V1.0 Created by 2020/9/20 11:06 | ||
| 67 | - */ | ||
| 68 | -@Service | ||
| 69 | -public class UserDetailsServiceImpl implements UmsUserDetailsService { | ||
| 70 | - | ||
| 71 | - private final Logger log = LoggerFactory.getLogger(this.getClass()); | ||
| 72 | - | ||
| 73 | - @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") | ||
| 74 | - @Autowired(required = false) | ||
| 75 | - private UserCache userCache; | ||
| 76 | - | ||
| 77 | - @Resource | ||
| 78 | - private SysUserService userService; | ||
| 79 | - | ||
| 80 | - /** | ||
| 81 | - * 用于密码加解密 | ||
| 82 | - */ | ||
| 83 | - @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") | ||
| 84 | - @Autowired | ||
| 85 | - private PasswordEncoder passwordEncoder; | ||
| 86 | - @Autowired | ||
| 87 | - private SysPermissionService permissionService; | ||
| 88 | - | ||
| 89 | - @SuppressWarnings("AlibabaUndefineMagicConstant") | ||
| 90 | - @Override | ||
| 91 | - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { | ||
| 92 | - | ||
| 93 | - try | ||
| 94 | - { | ||
| 95 | - // 从缓存中查询用户信息: | ||
| 96 | - // 从缓存中查询用户信息 | ||
| 97 | - if (this.userCache != null) | ||
| 98 | - { | ||
| 99 | - UserDetails userDetails = this.userCache.getUserFromCache(username); | ||
| 100 | - if (userDetails != null) | ||
| 101 | - { | ||
| 102 | - return userDetails; | ||
| 103 | - } | ||
| 104 | - } | ||
| 105 | - // 根据用户名获取用户信息 | ||
| 106 | - // 获取 username 对应的 SysUserDO | ||
| 107 | - SysUserDO user = userService.getUserByUsername(username); | ||
| 108 | - if (user == null) { | ||
| 109 | - throw new UsernameNotFoundException(username); | ||
| 110 | - } | ||
| 111 | - // 创建 LoginUser 对象 | ||
| 112 | - Auth2LoginUser loginUser = SysAuthConvert.INSTANCE.getAuth2LoginUser(user); | ||
| 113 | - //TODO 登录日志等可以和用户名密码等兼容处理 | ||
| 114 | - return loginUser; | ||
| 115 | - } | ||
| 116 | - catch (Exception e) | ||
| 117 | - { | ||
| 118 | - String msg = String.format("第三方登录 ======>: 登录用户名:%s, 登录失败: %s", username, e.getMessage()); | ||
| 119 | - log.error(msg); | ||
| 120 | - throw new UserNotExistException(ErrorCodeEnum.QUERY_USER_INFO_ERROR, e, username); | ||
| 121 | - } | ||
| 122 | - } | ||
| 123 | - | ||
| 124 | - @Override | ||
| 125 | - public UserDetails registerUser(@NonNull AuthUser authUser, @NonNull String username, | ||
| 126 | - @NonNull String defaultAuthority, String decodeState) throws RegisterUserFailureException { | ||
| 127 | - | ||
| 128 | - // 这里的 decodeState 可以根据自己实现的 top.dcenter.ums.security.core.oauth.service.Auth2StateCoder 接口的逻辑来传递必要的参数. | ||
| 129 | - // 比如: 第三方登录成功后的跳转地址 | ||
| 130 | - final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); | ||
| 131 | - // 假设 decodeState 就是 redirectUrl, 我们直接把 redirectUrl 设置到 request 上 | ||
| 132 | - // 后续经过成功处理器时直接从 requestAttributes.getAttribute("redirectUrl", RequestAttributes.SCOPE_REQUEST) 获取并跳转 | ||
| 133 | - if (requestAttributes != null) { | ||
| 134 | - requestAttributes.setAttribute("redirectUrl", decodeState, RequestAttributes.SCOPE_REQUEST); | ||
| 135 | - } | ||
| 136 | - //返回用户 | ||
| 137 | - LoginUser loginUser = doRegistUser(authUser); | ||
| 138 | - | ||
| 139 | - log.info("第三方用户注册 ======>: 用户名:{}, 注册成功", username); | ||
| 140 | - | ||
| 141 | - // 把用户信息存入缓存 | ||
| 142 | - if (userCache != null) | ||
| 143 | - { | ||
| 144 | - userCache.putUserInCache(loginUser); | ||
| 145 | - } | ||
| 146 | - | ||
| 147 | - return loginUser; | ||
| 148 | - } | ||
| 149 | - | ||
| 150 | - private LoginUser doRegistUser(AuthUser authUser) { | ||
| 151 | - SysUserCreateReqVO reqVO = SysAuthConvert.INSTANCE.convert(authUser); | ||
| 152 | - if (StringUtils.isEmpty(reqVO.getPassword())) { | ||
| 153 | - reqVO.setPassword(getDefaultPassword()); | ||
| 154 | - } | ||
| 155 | - //添加用户 | ||
| 156 | - Long sysUserId = userService.createUser(reqVO); | ||
| 157 | - //关联第三方用户 | ||
| 158 | - Long userId = userService.bindSocialUSer(sysUserId, authUser.getUuid()); | ||
| 159 | - //赋予默认角色权限;三方登录默认部分 | ||
| 160 | - permissionService.assignUserRole(userId, getDefaultRoles()); | ||
| 161 | - LoginUser loginUser = SysAuthConvert.INSTANCE.getLoginUser(authUser); | ||
| 162 | - loginUser.setRoleIds(getDefaultRoles()); | ||
| 163 | - loginUser.setPassword(getDefaultPassword()); | ||
| 164 | - loginUser.setId(sysUserId); | ||
| 165 | - return loginUser; | ||
| 166 | - } | ||
| 167 | - | ||
| 168 | - private String getDefaultPassword() { | ||
| 169 | - return "123456"; | ||
| 170 | - } | ||
| 171 | - | ||
| 172 | - protected Set<Long> getDefaultRoles() { | ||
| 173 | - return Sets.newHashSet(1L); | ||
| 174 | - } | ||
| 175 | - | ||
| 176 | - @NonNull | ||
| 177 | - public UserDetails registerUser(@NonNull String mobile, Map<String, String> otherParamMap) throws RegisterUserFailureException { | ||
| 178 | - | ||
| 179 | - // 用户信息持久化逻辑。。。 | ||
| 180 | - // ... | ||
| 181 | - | ||
| 182 | - log.info("Demo ======>: 手机短信登录用户 {}:注册成功", mobile); | ||
| 183 | - | ||
| 184 | - User user = new User(mobile, | ||
| 185 | - passwordEncoder.encode("admin"), | ||
| 186 | - true, | ||
| 187 | - true, | ||
| 188 | - true, | ||
| 189 | - true, | ||
| 190 | - AuthorityUtils.commaSeparatedStringToAuthorityList("admin, ROLE_USER") | ||
| 191 | - ); | ||
| 192 | - | ||
| 193 | - // 把用户信息存入缓存 | ||
| 194 | - if (userCache != null) | ||
| 195 | - { | ||
| 196 | - userCache.putUserInCache(user); | ||
| 197 | - } | ||
| 198 | - | ||
| 199 | - return user; | ||
| 200 | - } | ||
| 201 | - | ||
| 202 | - /** | ||
| 203 | - * {@link #existedByUsernames(String...)} usernames 生成规则. | ||
| 204 | - * 如需自定义重新实现此逻辑 | ||
| 205 | - * @param authUser 第三方用户信息 | ||
| 206 | - * @return 返回一个 username 数组 | ||
| 207 | - */ | ||
| 208 | - @Override | ||
| 209 | - public String[] generateUsernames(AuthUser authUser) { | ||
| 210 | - return new String[]{ | ||
| 211 | - authUser.getUsername(), | ||
| 212 | - // providerId = authUser.getSource() | ||
| 213 | - authUser.getUsername() + "_" + authUser.getSource(), | ||
| 214 | - // providerUserId = authUser.getUuid() | ||
| 215 | - authUser.getUsername() + "_" + authUser.getSource() + "_" + authUser.getUuid() | ||
| 216 | - }; | ||
| 217 | - } | ||
| 218 | - | ||
| 219 | - @Override | ||
| 220 | - public UserDetails loadUserByUserId(String userId) throws UsernameNotFoundException { | ||
| 221 | - UserDetails userDetails = loadUserByUsername(userId); | ||
| 222 | - User.withUserDetails(userDetails); | ||
| 223 | - return userDetails; | ||
| 224 | - } | ||
| 225 | - | ||
| 226 | - @Override | ||
| 227 | - public List<Boolean> existedByUsernames(String... usernames) throws UsernameNotFoundException { | ||
| 228 | - // ... 在本地账户上查询 userIds 是否已被使用 | ||
| 229 | - List<Boolean> list = new ArrayList<>(); | ||
| 230 | - for (String username : usernames) { | ||
| 231 | - SysUserDO userDO = userService.getUserByUsername(username); | ||
| 232 | - list.add(userDO != null); | ||
| 233 | - } | ||
| 234 | - return list; | ||
| 235 | - } | ||
| 236 | - | ||
| 237 | -} | ||
| 238 | \ No newline at end of file | 0 | \ No newline at end of file |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImpl.java
| @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; | @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.hutool.core.io.IoUtil; | 4 | import cn.hutool.core.io.IoUtil; |
| 5 | import cn.hutool.core.util.IdUtil; | 5 | import cn.hutool.core.util.IdUtil; |
| 6 | import cn.hutool.core.util.StrUtil; | 6 | import cn.hutool.core.util.StrUtil; |
| 7 | -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysUserSocialDO; | 7 | +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserSocialDO; |
| 8 | import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social.SysUserSocialMapper; | 8 | import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social.SysUserSocialMapper; |
| 9 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 9 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 10 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 10 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| @@ -82,7 +82,7 @@ public class SysUserServiceImpl implements SysUserService { | @@ -82,7 +82,7 @@ public class SysUserServiceImpl implements SysUserService { | ||
| 82 | public Long bindSocialUSer(Long sysUserId, String socialUSerId) { | 82 | public Long bindSocialUSer(Long sysUserId, String socialUSerId) { |
| 83 | SysUserSocialDO userSocialDO = new SysUserSocialDO(); | 83 | SysUserSocialDO userSocialDO = new SysUserSocialDO(); |
| 84 | userSocialDO.setUserId(sysUserId); | 84 | userSocialDO.setUserId(sysUserId); |
| 85 | - userSocialDO.setSocialUserId(socialUSerId); | 85 | +// userSocialDO.setSocialUserId(socialUSerId); |
| 86 | userSocialMapper.insert(userSocialDO); | 86 | userSocialMapper.insert(userSocialDO); |
| 87 | return userSocialDO.getUserId(); | 87 | return userSocialDO.getUserId(); |
| 88 | } | 88 | } |
yudao-admin-server/src/main/resources/application-local.yaml
| @@ -168,220 +168,13 @@ yudao: | @@ -168,220 +168,13 @@ yudao: | ||
| 168 | - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 | 168 | - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 |
| 169 | demo: false # 关闭演示模式 | 169 | demo: false # 关闭演示模式 |
| 170 | 170 | ||
| 171 | - | ||
| 172 | -# ums core | ||
| 173 | -ums: | ||
| 174 | - one-click-login: | ||
| 175 | - # 一键登录是否开启, 默认 false | ||
| 176 | - enable: true | ||
| 177 | - # 一键登录请求处理 url, 默认 /authentication/one-click | ||
| 178 | - login-processing-url: /authentication/one-click | ||
| 179 | - # token 参数名称, 默认: accessToken | ||
| 180 | - token-param-name: accessToken | ||
| 181 | - # 其他请求参数名称列表(包括请求头名称), 此参数会传递到 OneClickLoginService.callback(String, Map) | ||
| 182 | - # 与 UserDetailsRegisterService.registerUser(String, Map); 默认为: 空 | ||
| 183 | - other-param-names: | ||
| 184 | - - imei | ||
| 185 | - # ================ 第三方授权登录相关配置 ================ | ||
| 186 | - oauth: | ||
| 187 | - # 第三方授权登录后如未注册用户是否支持自动注册功能, 默认: true | ||
| 188 | - auto-sign-up: true | ||
| 189 | - # 第三方授权登录后如未注册用户不支持自动注册功能, 则跳转到此 url 进行注册逻辑, 此 url 必须开发者自己实现; 默认: /signUp.html; | ||
| 190 | - # 注意: 当 autoSignUp = false 时, 此属性才生效. | ||
| 191 | - # 例如: 1. 设置值 "/signUp", 则跳转指定到 "/signUp" 进行注册. | ||
| 192 | - # 2. 想返回自定义 json 数据到前端, 这里要设置 null , 在 Auth2LoginAuthenticationFilter 设置的 AuthenticationSuccessHandler | ||
| 193 | - # 上处理返回 json; 判断是否为临时用户的条件是: Authentication.getPrincipal() 是否为 TemporaryUser 类型. | ||
| 194 | - sign-up-url: null | ||
| 195 | - # 用于第三方授权登录时, 未开启自动注册且用户是第一次授权登录的临时用户密码, 默认为: "". 注意: 生产环境更换密码 | ||
| 196 | - temporary-user-password: "" | ||
| 197 | - # 用于第三方授权登录时, 未开启自动注册且用户是第一次授权登录的临时用户的默认权限, 多个权限用逗号分开, 默认为: "ROLE_TEMPORARY_USER" | ||
| 198 | - temporary-user-authorities: ROLE_TEMPORARY_USER | ||
| 199 | - # 抑制反射警告, 支持 JDK11, 默认: false , 在确认 WARNING: An illegal reflective access operation has occurred 安全后, 可以打开此设置, 可以抑制反射警告. | ||
| 200 | - suppress-reflect-warning: true | ||
| 201 | - # 第三方服务商: providerId, 支持所有 JustAuth 支持的第三方授权登录, 目前有 32 家第三方授权登录 | ||
| 202 | - github: | ||
| 203 | - # 根据是否有设置 clientId 来动态加载相应 JustAuth 的 AuthXxxRequest | ||
| 204 | - client-id: 4d4ee00e82f669f2ea8d | ||
| 205 | - client-secret: 4050be113a83556b63bd991d606fded437b05235 | ||
| 206 | - scopes: | ||
| 207 | - # - 'repo:status' | ||
| 208 | - # - 'public_repo' | ||
| 209 | - # - 'repo:invite' | ||
| 210 | - # - 'user:follow' | ||
| 211 | - gitee: | ||
| 212 | - client-id: eb5e3298cc10ead57cd40f9f36e7154ab2ea54dcb519684d7e10ca3fec5b1c1a | ||
| 213 | - client-secret: 495b5542dc007e2d46d316c527bd05dac586f2ec31b96c551e164387b5edb1cb | ||
| 214 | - scopes: | ||
| 215 | - - user_info | ||
| 216 | -# # 自定义 OAuth2 Login | ||
| 217 | -# customize: | ||
| 218 | -# client-id: c971cf1634460e18310a5d7cb0f55d7d143a72015b2f29aee6a0e8911efac7eb | ||
| 219 | -# client-secret: 309c9521721e3eb385a99a6bde2755f3107c7e15f3b8e0527c9f3ea4d1ce33bb | ||
| 220 | -# # 自定义第三方授权登录时, 当 Auth2Properties#customize 时有效, 此字段必须以驼峰方式命名. | ||
| 221 | -# # 比如此字段的值为 umsCustomize, 那么 /auth2/authorization/customize 会替换为 /auth2/authorization/umsCustomize | ||
| 222 | -# customize-provider-id: giteeCustomize | ||
| 223 | -# # 自定义第三方授权登录, 当 Auth2Properties#customize 时有效, 设置第三方是否在国外, 默认: false. | ||
| 224 | -# # 如果为 false 时, 设置 {@link HttpConfig} 的超时时间为 ums.oauth.proxy.timeout 的值. | ||
| 225 | -# # 如果为 true 时, 设置 {@link HttpConfig} 的超时时间为 ums.oauth.proxy.foreignTimeout 的值. | ||
| 226 | -# customize-is-foreign: false | ||
| 227 | - # 第三方登录授权登录 url 前缀, 不包含 ServletContextPath,默认为 /auth2/authorization. | ||
| 228 | - auth-login-url-prefix: /api/auth2/authorization | ||
| 229 | - # 第三方登录回调处理 url 前缀 ,也就是 RedirectUrl 的前缀, 不包含 ServletContextPath,默认为 /auth2/login. | ||
| 230 | - redirect-url-prefix: /api/auth2/login | ||
| 231 | - # 第三方登录回调的域名, 例如:http://localhost:9090 默认为 "http://127.0.0.1", | ||
| 232 | - # redirectUrl 直接由 {domain}/{servletContextPath}/{redirectUrlPrefix}/{providerId}(ums.oauth.[qq/gitee/weibo])组成 | ||
| 233 | - domain: http://localhost:48080 | ||
| 234 | - # 第三方授权登录成功后的默认权限, 多个权限用逗号分开, 默认为: "ROLE_USER" | ||
| 235 | - default-authorities: ROLE_USER | ||
| 236 | - # 是否支持内置的第三方登录用户表(user_connection) 和 auth_token 表. 默认: true. | ||
| 237 | - # 注意: 如果为 false, 则必须重新实现 ConnectionService 接口. | ||
| 238 | - enable-user-connection-and-auth-token-table: true | ||
| 239 | - # 是否支持内置的第三方登录 token 表(auth_token). 默认: true. | ||
| 240 | - enable-auth-token-table: true | ||
| 241 | - | ||
| 242 | - | ||
| 243 | - # ================ start: 定时刷新 access token 定时任务相关配置 ================ | ||
| 244 | - | ||
| 245 | - # 是否支持定时刷新 AccessToken 定时任务. 默认: false. | ||
| 246 | - # 支持分布式(分布式 IOC 容器中必须有 RedisConnectionFactory, 也就是说, 是否分布式执行依据 IOC 容器中是否有 RedisConnectionFactory) | ||
| 247 | - enableRefreshTokenJob: false | ||
| 248 | - # A cron-like expression. 0 * 2 * * ? 分别对应: second/minute/hour/day of month/month/day of week, | ||
| 249 | - # 默认为: "0 * 2 * * ?", 凌晨 2 点启动定时任务, 支持分布式(分布式 IOC 容器中必须有 {@link RedisConnectionFactory}, | ||
| 250 | - # 也就是说, 是否分布式执行依据 IOC 容器中是否有 {@link RedisConnectionFactory}) | ||
| 251 | - refresh-token-job-cron: 0 0/5 * * * ? | ||
| 252 | - # 定时刷新 accessToken 任务时, 批处理数据库的记录数. 注意: 分布式应用时, 此配置不同服务器配置必须是一样的. batchCount 大小需要根据实际生产环境进行优化 | ||
| 253 | - batch-count: 1000 | ||
| 254 | - # accessToken 的剩余有效期内进行刷新 accessToken, 默认: 24, 单位: 小时. 注意: 需要根据实际生产环境进行优化 | ||
| 255 | - remaining-expire-in: 24 | ||
| 256 | - | ||
| 257 | - # ================ start: 定时刷新 access token 定时任务相关配置 ================ | ||
| 258 | - | ||
| 259 | - # JustAuth 内部参数设置 | ||
| 260 | - just-auth: | ||
| 261 | - # 忽略校验 state 参数,默认不开启。当 ignoreCheckState 为 true 时, me.zhyd.oauth.request.AuthDefaultRequest.login(AuthCallback) 将不会校验 state 的合法性。 | ||
| 262 | - # 使用场景:当且仅当使用自实现 state 校验逻辑时开启 | ||
| 263 | - # 以下场景使用方案仅作参考: | ||
| 264 | - # 1. 授权、登录为同端,并且全部使用 JustAuth 实现时,该值建议设为 false; | ||
| 265 | - # 2. 授权和登录为不同端实现时,比如前端页面拼装 authorizeUrl,并且前端自行对state进行校验,后端只负责使用code获取用户信息时,该值建议设为 true; | ||
| 266 | - # 如非特殊需要,不建议开启这个配置 | ||
| 267 | - # 该方案主要为了解决以下类似场景的问题:Since: 1.15.6, See Also: https://github.com/justauth/JustAuth/issues/83 | ||
| 268 | - ignoreCheckState: false | ||
| 269 | - # 默认 state 缓存过期时间:3分钟(PT180S) 鉴于授权过程中,根据个人的操作习惯,或者授权平台的不同(google等),每个授权流程的耗时也有差异, | ||
| 270 | - # 不过单个授权流程一般不会太长 本缓存工具默认的过期时间设置为3分钟,即程序默认认为3分钟内的授权有效,超过3分钟则默认失效,失效后删除 | ||
| 271 | - # 注意: 这是为了测试打断点时用的, 生产环境自己设置为合适数组或默认 | ||
| 272 | - timeout: PT1800S | ||
| 273 | - # JustAuth state 缓存类型, 默认 session | ||
| 274 | - cacheType: session | ||
| 275 | - # JustAuth state 缓存 key 前缀 | ||
| 276 | - cacheKeyPrefix: 'JUST_AUTH:' | ||
| 277 | - | ||
| 278 | - # 用于 JustAuth 的代理(HttpClient)设置 | ||
| 279 | - proxy: | ||
| 280 | - # 是否支持代理, 默认为: false. | ||
| 281 | - enable: false | ||
| 282 | - # 针对国外服务可以单独设置代理类型, 默认 Proxy.Type.HTTP, enable = true 时生效. | ||
| 283 | - proxy: HTTP | ||
| 284 | - # 代理 host, enable = true 时生效. | ||
| 285 | - hostname: | ||
| 286 | - # 代理端口, enable = true 时生效. | ||
| 287 | - port: | ||
| 288 | - # 用于国内代理(HttpClient)超时, 默认 PT3S | ||
| 289 | - timeout: PT3S | ||
| 290 | - # 用于国外网站代理(HttpClient)超时, 默认 PT15S | ||
| 291 | - foreign-timeout: PT150S | ||
| 292 | - | ||
| 293 | - | ||
| 294 | - # =============== start: 第三方登录时用的数据库表 user_connection 与 auth_token 添加 redis cache =============== | 171 | +justauth: |
| 172 | + enabled: true | ||
| 173 | + type: | ||
| 174 | + GITEE: | ||
| 175 | + client-id: 6bb0b37a8a017e5e2dc4c34ca4756dcf80e8e392585e7035d3ede7a6db50426e | ||
| 176 | + client-secret: f117b9de5e9267bcd48db83d4cb078ea8cf9a5d17cda83481e3d9090df3fa01d | ||
| 177 | + ignore-check-redirect-uri: true | ||
| 178 | +# redirect-uri: http://127.0.0.1:48080/api/gitee/callback | ||
| 295 | cache: | 179 | cache: |
| 296 | - # redisCacheManager 设置, 默认实现: 对查询结果 null 值进行缓存, 添加时更新缓存 null 值. | ||
| 297 | - redis: | ||
| 298 | - # 是否开启缓存, 默认 false | ||
| 299 | - open: false | ||
| 300 | - # 是否使用 spring IOC 容器中的 RedisConnectionFactory, 默认: false | ||
| 301 | - # 如果使用 spring IOC 容器中的 RedisConnectionFactory,则要注意 cache.database-index 要与 spring.redis.database 一样。 | ||
| 302 | - use-ioc-redis-connection-factory: true | ||
| 303 | - cache: | ||
| 304 | - # redis cache 存放的 database index, 默认: 0 | ||
| 305 | - database-index: 1 | ||
| 306 | - # 设置缓存管理器管理的缓存的默认过期时间, 默认: 200s | ||
| 307 | - default-expire-time: PT200S | ||
| 308 | - # cache ttl 。使用 0 声明一个永久的缓存。 默认: 180, 单位: 秒<br> | ||
| 309 | - # 取缓存时间的 20% 作为动态的随机变量上下浮动, 防止同时缓存失效而缓存击穿 | ||
| 310 | - entry-ttl: PT180S | ||
| 311 | - # Names of the default caches to consider for caching operations defined in the annotated class. | ||
| 312 | - # 此设置不对 user_connection 与 auth_token 使用的缓存名称(UCC/UCHC/UCHACC)产生影响. | ||
| 313 | - cache-names: | ||
| 314 | - - cacheName | ||
| 315 | - # =============== end: 第三方登录时用的数据库表 user_connection 与 auth_token 添加 redis cache =============== | ||
| 316 | - | ||
| 317 | - # =============== start: 线程池配置 =============== | ||
| 318 | - executor: | ||
| 319 | - # 启动第三方授权登录用户的 accessToken 的定时任务时的 Executor 属性, 注意: 需要根据实际生产环境进行优化 | ||
| 320 | - job-task-scheduled-executor: | ||
| 321 | - # 线程池中空闲时保留的线程数, 默认: 0 | ||
| 322 | - core-pool-size: 0 | ||
| 323 | - # keep alive time, 默认: 10 | ||
| 324 | - keep-alive-time: 0 | ||
| 325 | - # keepAliveTime 时间单位, 默认: 毫秒 | ||
| 326 | - time-unit: milliseconds | ||
| 327 | - # 线程池名称, 默认: accessTokenJob | ||
| 328 | - pool-name: accessTokenJob | ||
| 329 | - # 拒绝策略, 默认: ABORT | ||
| 330 | - rejected-execution-handler-policy: abort | ||
| 331 | - # 线程池关闭过程的超时时间, 默认: PT10S | ||
| 332 | - executor-shutdown-timeout: PT10S | ||
| 333 | - # 更新第三方授权登录用户的 accessToken 的执行逻辑, 向本地数据库 auth_token 表获取过期或在一定时间内过期的 token 记录, | ||
| 334 | - # 用 refreshToken 向第三方服务商更新 accessToken 信息的 Executor 属性, | ||
| 335 | - # 注意: 定时刷新 accessToken 的执行逻辑是多线程的, 需要根据实际生产环境进行优化 | ||
| 336 | - refresh-token: | ||
| 337 | - # 程池中空闲时保留的线程数, 默认: 0 | ||
| 338 | - core-pool-size: 0 | ||
| 339 | - # 最大线程数, 默认: 本机核心数 | ||
| 340 | - maximum-pool-size: 8 | ||
| 341 | - # keep alive time, 默认: 5 | ||
| 342 | - keep-alive-time: 5 | ||
| 343 | - # keepAliveTime 时间单位, 默认: 秒 | ||
| 344 | - time-unit: seconds | ||
| 345 | - # blocking queue capacity, 默认: maximumPoolSize * 2 | ||
| 346 | - blocking-queue-capacity: 16 | ||
| 347 | - # 线程池名称, 默认: refreshToken | ||
| 348 | - pool-name: refreshToken | ||
| 349 | - # 拒绝策略, 默认: CALLER_RUNS 注意: 一般情况下不要更改默认设置, 没有实现 RefreshToken 逻辑被拒绝执行后的处理逻辑, 除非自己实现RefreshTokenJob.refreshTokenJob() 对 RefreshToken 逻辑被拒绝执行后的处理逻辑. | ||
| 350 | - rejected-execution-handler-policy: caller_runs | ||
| 351 | - # 线程池关闭过程的超时时间, 默认: 10 秒 | ||
| 352 | - executor-shutdown-timeout: PT10S | ||
| 353 | - # 第三方授权登录时, 异步更新用户的第三方授权用户信息与 token 信息的 Executor 属性, | ||
| 354 | - # 注意: 第三方授权登录时是异步更新第三方用户信息与 token 信息到本地数据库时使用此配置, 需要根据实际生产环境进行优化 | ||
| 355 | - user-connection-update: | ||
| 356 | - # 程池中空闲时保留的线程数, 默认: 5 | ||
| 357 | - core-pool-size: 5 | ||
| 358 | - # 最大线程数, 默认: 本机核心数 | ||
| 359 | - maximum-pool-size: 8 | ||
| 360 | - # keep alive time, 默认: 10 | ||
| 361 | - keep-alive-time: | ||
| 362 | - # keepAliveTime 时间单位, 默认: 秒 | ||
| 363 | - time-unit: seconds | ||
| 364 | - # blocking queue capacity, 默认: maximumPoolSize * 2 | ||
| 365 | - blocking-queue-capacity: 16 | ||
| 366 | - # 线程池名称, 默认: updateConnection | ||
| 367 | - pool-name: updateConnection | ||
| 368 | - # 拒绝策略, 默认: CALLER_RUNS 注意: 一般情况下不要更改默认设置, 除非自己实现Auth2LoginAuthenticationProvider更新逻辑; | ||
| 369 | - # 改成 ABORT 也支持, 默认实现 Auth2LoginAuthenticationProvider 是异步更新被拒绝执行后, 会执行同步更新. | ||
| 370 | - rejected-execution-handler-policy: caller_runs | ||
| 371 | - # 线程池关闭过程的超时时间, 默认: PT10S | ||
| 372 | - executor-shutdown-timeout: PT10S | ||
| 373 | - # =============== end: 线程池配置 =============== | ||
| 374 | - | ||
| 375 | - # =============== start: user_connection repository 配置 =============== | ||
| 376 | - repository: | ||
| 377 | - | ||
| 378 | - # 第三方登录用户数据库表的字段 accessToken 与 refreshToken 加密专用密码 | ||
| 379 | - text-encryptor-password: 7ca5d913a17b4942942d16a974e3fecc | ||
| 380 | - # 第三方登录用户数据库表的字段 accessToken 与 refreshToken 加密专用 salt | ||
| 381 | - text-encryptor-salt: cd538b1b077542aca5f86942b6507fe2 | ||
| 382 | - # 是否在启动时检查并自动创建 userConnectionTableName 与 authTokenTableName, 默认: TRUE | ||
| 383 | - enableStartUpInitializeTable: true | ||
| 384 | - # 其他的有: 数据库表名称, 字段名称, curd sql 语句 等设置, 一般不需要更改, | ||
| 385 | - # 如果要添加字段: 具体查看 RepositoryProperties 与 Auth2JdbcUsersConnectionRepository | ||
| 386 | - # =============== end: user_connection repository 配置 =============== | ||
| 387 | - | 180 | + type: default |
yudao-admin-ui/src/api/login.js
| @@ -40,9 +40,9 @@ export function getCodeImg() { | @@ -40,9 +40,9 @@ export function getCodeImg() { | ||
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | // 接入第三方登录 | 42 | // 接入第三方登录 |
| 43 | -export function oAuthLogin(provider) { | 43 | +export function oAuthLogin(type, redirectUri) { |
| 44 | return request({ | 44 | return request({ |
| 45 | - url: '/auth2/authorization/' + provider, | 45 | + url: '/third-login-redirect?type=' + type + '&redirectUri=' + redirectUri, |
| 46 | method: 'get' | 46 | method: 'get' |
| 47 | }) | 47 | }) |
| 48 | } | 48 | } |
yudao-admin-ui/src/views/login.vue
| @@ -8,24 +8,12 @@ | @@ -8,24 +8,12 @@ | ||
| 8 | </el-input> | 8 | </el-input> |
| 9 | </el-form-item> | 9 | </el-form-item> |
| 10 | <el-form-item prop="password"> | 10 | <el-form-item prop="password"> |
| 11 | - <el-input | ||
| 12 | - v-model="loginForm.password" | ||
| 13 | - type="password" | ||
| 14 | - auto-complete="off" | ||
| 15 | - placeholder="密码" | ||
| 16 | - @keyup.enter.native="handleLogin" | ||
| 17 | - > | 11 | + <el-input v-model="loginForm.password" type="password" auto-complete="off" placeholder="密码" @keyup.enter.native="handleLogin"> |
| 18 | <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> | 12 | <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> |
| 19 | </el-input> | 13 | </el-input> |
| 20 | </el-form-item> | 14 | </el-form-item> |
| 21 | <el-form-item prop="code"> | 15 | <el-form-item prop="code"> |
| 22 | - <el-input | ||
| 23 | - v-model="loginForm.code" | ||
| 24 | - auto-complete="off" | ||
| 25 | - placeholder="验证码" | ||
| 26 | - style="width: 63%" | ||
| 27 | - @keyup.enter.native="handleLogin" | ||
| 28 | - > | 16 | + <el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter.native="handleLogin"> |
| 29 | <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> | 17 | <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> |
| 30 | </el-input> | 18 | </el-input> |
| 31 | <div class="login-code"> | 19 | <div class="login-code"> |
| @@ -34,18 +22,12 @@ | @@ -34,18 +22,12 @@ | ||
| 34 | </el-form-item> | 22 | </el-form-item> |
| 35 | <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox> | 23 | <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox> |
| 36 | <el-form-item style="width:100%;"> | 24 | <el-form-item style="width:100%;"> |
| 37 | - <el-button | ||
| 38 | - :loading="loading" | ||
| 39 | - size="medium" | ||
| 40 | - type="primary" | ||
| 41 | - style="width:100%;" | ||
| 42 | - @click.native.prevent="handleLogin" | ||
| 43 | - > | 25 | + <el-button :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin"> |
| 44 | <span v-if="!loading">登 录</span> | 26 | <span v-if="!loading">登 录</span> |
| 45 | <span v-else>登 录 中...</span> | 27 | <span v-else>登 录 中...</span> |
| 46 | </el-button> | 28 | </el-button> |
| 47 | </el-form-item> | 29 | </el-form-item> |
| 48 | - | 30 | + |
| 49 | <el-form-item style="width:100%;"> | 31 | <el-form-item style="width:100%;"> |
| 50 | <div class="oauth-login" style="display:flex"> | 32 | <div class="oauth-login" style="display:flex"> |
| 51 | <div class="oauth-login-item" v-for="item in oauthProviders" :key="item.code" @click="doAuth2Login(item)"> | 33 | <div class="oauth-login-item" v-for="item in oauthProviders" :key="item.code" @click="doAuth2Login(item)"> |
| @@ -80,21 +62,19 @@ export default { | @@ -80,21 +62,19 @@ export default { | ||
| 80 | code: "", | 62 | code: "", |
| 81 | uuid: "" | 63 | uuid: "" |
| 82 | }, | 64 | }, |
| 83 | - oauthProviders: [ | ||
| 84 | - { | 65 | + oauthProviders: [{ |
| 85 | img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.2/gitee.png", | 66 | img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.2/gitee.png", |
| 86 | title: "码云", | 67 | title: "码云", |
| 87 | - code: "gitee" | ||
| 88 | - }, | ||
| 89 | - { | 68 | + source: "gitee", |
| 69 | + type: 10 | ||
| 70 | + }, { | ||
| 90 | img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.2/wechat.png", | 71 | img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.2/wechat.png", |
| 91 | title: "微信", | 72 | title: "微信", |
| 92 | - code: "weixin" | ||
| 93 | - }, | ||
| 94 | - { | 73 | + source: "weixin" |
| 74 | + }, { | ||
| 95 | img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.2/qq.png", | 75 | img: "https://cdn.jsdelivr.net/gh/justauth/justauth-oauth-logo@1.2/qq.png", |
| 96 | title: "QQ", | 76 | title: "QQ", |
| 97 | - code: "qq" | 77 | + source: "qq" |
| 98 | } | 78 | } |
| 99 | ], | 79 | ], |
| 100 | loginRules: { | 80 | loginRules: { |
| @@ -163,11 +143,15 @@ export default { | @@ -163,11 +143,15 @@ export default { | ||
| 163 | }); | 143 | }); |
| 164 | }, | 144 | }, |
| 165 | doAuth2Login(provider) { | 145 | doAuth2Login(provider) { |
| 166 | - console.log("开始Oauth登录...%o", provider.code); | 146 | + // console.log("开始Oauth登录...%o", provider.code); |
| 147 | + // 设置登陆中 | ||
| 167 | this.loading = true; | 148 | this.loading = true; |
| 168 | - oAuthLogin(provider.code).then((res) => { | ||
| 169 | - console.log(res.url); | ||
| 170 | - window.location.href = res.url; | 149 | + // 计算 redirectUri |
| 150 | + const redirectUri = location.origin + '/third-login'; | ||
| 151 | + // 进行跳转 | ||
| 152 | + oAuthLogin(provider.type, redirectUri).then((res) => { | ||
| 153 | + // console.log(res.url); | ||
| 154 | + window.location.href = res.data; | ||
| 171 | }); | 155 | }); |
| 172 | } | 156 | } |
| 173 | } | 157 | } |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.common.util.http; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.io.FileUtil; | ||
| 4 | +import cn.hutool.core.map.TableMap; | ||
| 5 | +import cn.hutool.core.net.url.UrlBuilder; | ||
| 6 | +import cn.hutool.core.util.ReferenceUtil; | ||
| 7 | +import cn.hutool.core.util.ReflectUtil; | ||
| 8 | + | ||
| 9 | +import java.nio.charset.Charset; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * HTTP 工具类 | ||
| 13 | + * | ||
| 14 | + * @author 芋道源码 | ||
| 15 | + */ | ||
| 16 | +public class HttpUtils { | ||
| 17 | + | ||
| 18 | + @SuppressWarnings("unchecked") | ||
| 19 | + public static String replaceUrlQuery(String url, String key, String value) { | ||
| 20 | + UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset()); | ||
| 21 | + // 先移除 | ||
| 22 | + TableMap<CharSequence, CharSequence> query = (TableMap<CharSequence, CharSequence>) | ||
| 23 | + ReflectUtil.getFieldValue(builder.getQuery(), "query"); | ||
| 24 | + query.remove(key); | ||
| 25 | + // 后添加 | ||
| 26 | + builder.addQuery(key, value); | ||
| 27 | + return builder.build(); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | +} |
yudao-framework/yudao-spring-boot-starter-security/pom.xml
| @@ -44,19 +44,6 @@ | @@ -44,19 +44,6 @@ | ||
| 44 | <artifactId>spring-boot-starter-security</artifactId> | 44 | <artifactId>spring-boot-starter-security</artifactId> |
| 45 | </dependency> | 45 | </dependency> |
| 46 | 46 | ||
| 47 | - <!-- justAuth 集成第三方登录 --> | ||
| 48 | - <dependency> | ||
| 49 | - <groupId>top.dcenter</groupId> | ||
| 50 | - <artifactId>justAuth-spring-security-starter</artifactId> | ||
| 51 | - <version>1.1.25</version> | ||
| 52 | - <exclusions> | ||
| 53 | - <exclusion> | ||
| 54 | - <artifactId>slf4j-api</artifactId> | ||
| 55 | - <groupId>org.slf4j</groupId> | ||
| 56 | - </exclusion> | ||
| 57 | - </exclusions> | ||
| 58 | - </dependency> | ||
| 59 | - | ||
| 60 | </dependencies> | 47 | </dependencies> |
| 61 | 48 | ||
| 62 | </project> | 49 | </project> |
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
| @@ -24,9 +24,6 @@ import org.springframework.security.web.access.AccessDeniedHandler; | @@ -24,9 +24,6 @@ import org.springframework.security.web.access.AccessDeniedHandler; | ||
| 24 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | 24 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; |
| 25 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | 25 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; |
| 26 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; | 26 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; |
| 27 | -import top.dcenter.ums.security.core.oauth.config.Auth2AutoConfigurer; | ||
| 28 | -import top.dcenter.ums.security.core.oauth.properties.Auth2Properties; | ||
| 29 | -import top.dcenter.ums.security.core.oauth.properties.OneClickLoginProperties; | ||
| 30 | 27 | ||
| 31 | import javax.annotation.Resource; | 28 | import javax.annotation.Resource; |
| 32 | 29 | ||
| @@ -80,15 +77,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | @@ -80,15 +77,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | ||
| 80 | @Resource | 77 | @Resource |
| 81 | private Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer; | 78 | private Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer; |
| 82 | 79 | ||
| 83 | - @Autowired | ||
| 84 | - private Auth2AutoConfigurer auth2AutoConfigurer; | ||
| 85 | - @Autowired | ||
| 86 | - private Auth2Properties auth2Properties; | ||
| 87 | - @Autowired | ||
| 88 | - private OneClickLoginProperties oneClickLoginProperties; | ||
| 89 | - @Autowired | ||
| 90 | - private AbstractSignUpUrlAuthenticationSuccessHandler authenticationSuccessHandler; | ||
| 91 | - | ||
| 92 | /** | 80 | /** |
| 93 | * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 | 81 | * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 |
| 94 | * 通过覆写父类的该方法,添加 @Bean 注解,解决该问题 | 82 | * 通过覆写父类的该方法,添加 @Bean 注解,解决该问题 |
| @@ -129,9 +117,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | @@ -129,9 +117,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | ||
| 129 | @Override | 117 | @Override |
| 130 | protected void configure(HttpSecurity httpSecurity) throws Exception { | 118 | protected void configure(HttpSecurity httpSecurity) throws Exception { |
| 131 | httpSecurity | 119 | httpSecurity |
| 132 | - // ========= start: 使用 justAuth-spring-security-starter 必须步骤 ========= | ||
| 133 | - // 添加 Auth2AutoConfigurer 使 OAuth2(justAuth) login 生效. | ||
| 134 | - .apply(this.auth2AutoConfigurer).and() | ||
| 135 | // 开启跨域 | 120 | // 开启跨域 |
| 136 | .cors().and() | 121 | .cors().and() |
| 137 | // CSRF 禁用,因为不使用 Session | 122 | // CSRF 禁用,因为不使用 Session |
| @@ -174,19 +159,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | @@ -174,19 +159,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | ||
| 174 | // 添加 JWT Filter | 159 | // 添加 JWT Filter |
| 175 | httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); | 160 | httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); |
| 176 | 161 | ||
| 177 | -// // 放行第三方登录入口地址与第三方登录回调地址 | ||
| 178 | -// // @formatter:off | ||
| 179 | -// httpSecurity.authorizeRequests() | ||
| 180 | -// .antMatchers(HttpMethod.GET, | ||
| 181 | -// auth2Properties.getRedirectUrlPrefix() + "/*", | ||
| 182 | -// auth2Properties.getAuthLoginUrlPrefix() + "/*") | ||
| 183 | -// .permitAll(); | ||
| 184 | -// httpSecurity.authorizeRequests() | ||
| 185 | -// .antMatchers(HttpMethod.POST, | ||
| 186 | -// oneClickLoginProperties.getLoginProcessingUrl()) | ||
| 187 | -// .permitAll(); | ||
| 188 | -// // @formatter:on | ||
| 189 | -// // ========= end: 使用 justAuth-spring-security-starter 必须步骤 ========= | ||
| 190 | } | 162 | } |
| 191 | 163 | ||
| 192 | private String api(String url) { | 164 | private String api(String url) { |
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/Auth2LoginUser.java deleted
| 1 | -package cn.iocoder.yudao.framework.security.core; | ||
| 2 | - | ||
| 3 | -import com.alibaba.fastjson.JSONObject; | ||
| 4 | -import lombok.AllArgsConstructor; | ||
| 5 | -import lombok.Data; | ||
| 6 | -import me.zhyd.oauth.enums.AuthUserGender; | ||
| 7 | -import me.zhyd.oauth.model.AuthToken; | ||
| 8 | - | ||
| 9 | -/** | ||
| 10 | - * @author weir | ||
| 11 | - */ | ||
| 12 | -@Data | ||
| 13 | -public class Auth2LoginUser extends LoginUser { | ||
| 14 | - /** | ||
| 15 | - * 是否为临时注册的临时用户 | ||
| 16 | - */ | ||
| 17 | - private boolean isTempUser; | ||
| 18 | - /** | ||
| 19 | - * 用户第三方系统的唯一id。在调用方集成该组件时,可以用uuid + source唯一确定一个用户 | ||
| 20 | - */ | ||
| 21 | - private String thirdPartyUserId; | ||
| 22 | - /** | ||
| 23 | - * 用户昵称 | ||
| 24 | - */ | ||
| 25 | - private String nickname; | ||
| 26 | - /** | ||
| 27 | - * 用户头像 | ||
| 28 | - */ | ||
| 29 | - private String avatar; | ||
| 30 | - /** | ||
| 31 | - * 用户网址 | ||
| 32 | - */ | ||
| 33 | - private String blog; | ||
| 34 | - /** | ||
| 35 | - * 所在公司 | ||
| 36 | - */ | ||
| 37 | - private String company; | ||
| 38 | - /** | ||
| 39 | - * 位置 | ||
| 40 | - */ | ||
| 41 | - private String location; | ||
| 42 | - /** | ||
| 43 | - * 用户邮箱 | ||
| 44 | - */ | ||
| 45 | - private String email; | ||
| 46 | - /** | ||
| 47 | - * 用户备注(各平台中的用户个人介绍) | ||
| 48 | - */ | ||
| 49 | - private String remark; | ||
| 50 | - /** | ||
| 51 | - * 性别 | ||
| 52 | - */ | ||
| 53 | - private AuthUserGender gender; | ||
| 54 | - /** | ||
| 55 | - * 用户来源 | ||
| 56 | - */ | ||
| 57 | - private String source; | ||
| 58 | - /** | ||
| 59 | - * 用户授权的token信息 | ||
| 60 | - */ | ||
| 61 | - private AuthToken token; | ||
| 62 | - /** | ||
| 63 | - * 第三方平台返回的原始用户信息 | ||
| 64 | - */ | ||
| 65 | - private JSONObject rawUserInfo; | ||
| 66 | -} |
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AbstractSignUpUrlAuthenticationSuccessHandler.java
| @@ -22,24 +22,16 @@ | @@ -22,24 +22,16 @@ | ||
| 22 | */ | 22 | */ |
| 23 | package cn.iocoder.yudao.framework.security.core.handler; | 23 | package cn.iocoder.yudao.framework.security.core.handler; |
| 24 | 24 | ||
| 25 | -import cn.iocoder.yudao.framework.security.core.LoginUser; | ||
| 26 | -import org.springframework.http.HttpStatus; | ||
| 27 | import org.springframework.security.core.Authentication; | 25 | import org.springframework.security.core.Authentication; |
| 28 | import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; | 26 | import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; |
| 29 | import org.springframework.security.web.savedrequest.HttpSessionRequestCache; | 27 | import org.springframework.security.web.savedrequest.HttpSessionRequestCache; |
| 30 | import org.springframework.security.web.savedrequest.RequestCache; | 28 | import org.springframework.security.web.savedrequest.RequestCache; |
| 31 | -import org.springframework.security.web.savedrequest.SavedRequest; | ||
| 32 | -import top.dcenter.ums.security.core.oauth.userdetails.TemporaryUser; | ||
| 33 | -import top.dcenter.ums.security.core.vo.ResponseResult; | ||
| 34 | 29 | ||
| 35 | import javax.servlet.ServletException; | 30 | import javax.servlet.ServletException; |
| 36 | import javax.servlet.http.HttpServletRequest; | 31 | import javax.servlet.http.HttpServletRequest; |
| 37 | import javax.servlet.http.HttpServletResponse; | 32 | import javax.servlet.http.HttpServletResponse; |
| 38 | import java.io.IOException; | 33 | import java.io.IOException; |
| 39 | 34 | ||
| 40 | -import static org.springframework.util.StringUtils.hasText; | ||
| 41 | -import static top.dcenter.ums.security.core.oauth.util.MvcUtil.*; | ||
| 42 | - | ||
| 43 | /** | 35 | /** |
| 44 | * @author weir | 36 | * @author weir |
| 45 | */ | 37 | */ |