From 5615b78c5e43f3f6daf02f4fe7dc6912c3d039cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B7=E5=86=B7?= Date: Mon, 8 Apr 2019 21:53:58 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E6=B7=BB=E5=8A=A0=E6=96=B0?= =?UTF-8?q?=E7=89=B9=E6=80=A7=E3=80=82=20=E6=94=AF=E6=8C=81=E5=BC=80?= =?UTF-8?q?=E6=BA=90=E4=B8=AD=E5=9B=BD=E3=80=81=E7=A0=81=E4=BA=91=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/AuthorizationServerConfig.java | 1 + .../pigx/auth/endpoint/PigxTokenEndpoint.java | 36 +++++- .../src/main/resources/static/css/signin.css | 2 +- .../main/resources/templates/ftl/confirm.ftl | 47 ++++++++ .../main/resources/templates/ftl/login.ftl | 4 +- .../core/constant/SecurityConstants.java | 22 ++++ .../core/constant/enums/LoginTypeEnum.java | 12 +- .../pigx/admin/api/entity/SysUser.java | 9 ++ .../pigx/admin/handler/GiteeLoginHandler.java | 103 ++++++++++++++++ .../admin/handler/OscChinaLoginHandler.java | 111 ++++++++++++++++++ .../admin/handler/WeChatLoginHandler.java | 1 - .../impl/SysSocialDetailsServiceImpl.java | 11 +- pom.xml | 2 +- 13 files changed, 352 insertions(+), 9 deletions(-) create mode 100644 pigx-auth/src/main/resources/templates/ftl/confirm.ftl create mode 100644 pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/GiteeLoginHandler.java create mode 100644 pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/OscChinaLoginHandler.java diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfig.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfig.java index d03dd0134..cf8906e74 100644 --- a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfig.java +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfig.java @@ -87,6 +87,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap .userDetailsService(pigxUserDetailsService) .authenticationManager(authenticationManagerBean) .reuseRefreshTokens(false) + .pathMapping("/oauth/confirm_access", "/token/confirm_access") .exceptionTranslator(new PigxWebResponseExceptionTranslator()); } diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/PigxTokenEndpoint.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/PigxTokenEndpoint.java index fb897a81c..265304ac4 100644 --- a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/PigxTokenEndpoint.java +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/PigxTokenEndpoint.java @@ -39,11 +39,16 @@ import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.http.HttpHeaders; import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.AuthorizationRequest; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -58,6 +63,7 @@ import java.util.Map; @RequestMapping("/token") public class PigxTokenEndpoint { private static final String PIGX_OAUTH_ACCESS = SecurityConstants.PIGX_PREFIX + SecurityConstants.OAUTH_PREFIX + "auth_to_access:"; + private final ClientDetailsService clientDetailsService; private final RedisTemplate pigxRedisTemplate; private final TokenStore tokenStore; private final CacheManager cacheManager; @@ -65,11 +71,37 @@ public class PigxTokenEndpoint { /** * 认证页面 * + * @param modelAndView * @return ModelAndView */ @GetMapping("/login") - public ModelAndView require() { - return new ModelAndView("ftl/login"); + public ModelAndView require(ModelAndView modelAndView) { + modelAndView.setViewName("ftl/login"); + return modelAndView; + } + + /** + * 确认授权页面 + * + * @param request + * @param session + * @param modelAndView + * @return + */ + @GetMapping("/confirm_access") + public ModelAndView confirm(HttpServletRequest request, HttpSession session, ModelAndView modelAndView) { + Map scopeList = (Map) request.getAttribute("scopes"); + modelAndView.addObject("scopeList", scopeList.keySet()); + + Object auth = session.getAttribute("authorizationRequest"); + if (auth != null) { + AuthorizationRequest authorizationRequest = (AuthorizationRequest) auth; + ClientDetails clientDetails = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); + modelAndView.addObject("app", clientDetails.getAdditionalInformation()); + } + + modelAndView.setViewName("ftl/confirm"); + return modelAndView; } /** diff --git a/pigx-auth/src/main/resources/static/css/signin.css b/pigx-auth/src/main/resources/static/css/signin.css index 10ee7d596..3f076188e 100755 --- a/pigx-auth/src/main/resources/static/css/signin.css +++ b/pigx-auth/src/main/resources/static/css/signin.css @@ -15,7 +15,7 @@ * Author: lengleng (wangiegie@gmail.com) */ -body { +.sign_body { padding-top: 40px; padding-bottom: 40px; background-color: #eee; diff --git a/pigx-auth/src/main/resources/templates/ftl/confirm.ftl b/pigx-auth/src/main/resources/templates/ftl/confirm.ftl new file mode 100644 index 000000000..30909ff63 --- /dev/null +++ b/pigx-auth/src/main/resources/templates/ftl/confirm.ftl @@ -0,0 +1,47 @@ + + + + + + + PigX第三方授权 + + + + + + +
+
+ +

${app.appName} 将获得以下权限:

+
    +
  • + <#list scopeList as scope> + + + +
+

授权后表明你已同意 服务协议

+ +

+
+
+ + + diff --git a/pigx-auth/src/main/resources/templates/ftl/login.ftl b/pigx-auth/src/main/resources/templates/ftl/login.ftl index becb0c495..3539f841e 100755 --- a/pigx-auth/src/main/resources/templates/ftl/login.ftl +++ b/pigx-auth/src/main/resources/templates/ftl/login.ftl @@ -14,7 +14,7 @@ - +
diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java index 5225be97f..90b0b45ef 100644 --- a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java @@ -93,6 +93,28 @@ public interface SecurityConstants { String WX_AUTHORIZATION_CODE_URL = "https://api.weixin.qq.com/sns/oauth2/access_token" + "?appid=%s&secret=%s&code=%s&grant_type=authorization_code"; + /** + * 码云获取token + */ + String GITEE_AUTHORIZATION_CODE_URL = "https://gitee.com/oauth/token?grant_type=" + + "authorization_code&code=%S&client_id=%s&redirect_uri=" + + "%s&client_secret=%s"; + + /** + * 开源中国获取token + */ + String OSC_AUTHORIZATION_CODE_URL = "https://www.oschina.net/action/openapi/token"; + + /** + * 码云获取用户信息 + */ + String GITEE_USER_INFO_URL = "https://gitee.com/api/v5/user?access_token=%s"; + + /** + * 开源中国用户信息 + */ + String OSC_USER_INFO_URL = "https://www.oschina.net/action/openapi/user?access_token=%s&dataType=json"; + /** * {bcrypt} 加密的特征码 */ diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/LoginTypeEnum.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/LoginTypeEnum.java index 33a245698..816c05ddd 100644 --- a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/LoginTypeEnum.java +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/enums/LoginTypeEnum.java @@ -46,7 +46,17 @@ public enum LoginTypeEnum { /** * 微信登录 */ - WECHAT("WX", "微信登录"); + WECHAT("WX", "微信登录"), + + /** + * 码云登录 + */ + GITEE("GITEE", "码云登录"), + + /** + * 开源中国登录 + */ + OSC("OSC", "开源中国登录"); /** * 类型 diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java index da1f943ca..c4dcbbd60 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/entity/SysUser.java @@ -105,4 +105,13 @@ public class SysUser implements Serializable { */ private String qqOpenid; + /** + * 码云唯一标识 + */ + private String giteeLogin; + + /** + * 开源中国唯一标识 + */ + private String oscId; } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/GiteeLoginHandler.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/GiteeLoginHandler.java new file mode 100644 index 000000000..09e6322a1 --- /dev/null +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/GiteeLoginHandler.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.admin.handler; + +import cn.hutool.core.util.URLUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.pig4cloud.pigx.admin.api.dto.UserInfo; +import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails; +import com.pig4cloud.pigx.admin.api.entity.SysUser; +import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper; +import com.pig4cloud.pigx.admin.service.SysUserService; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.HashMap; + +/** + * @author lengleng + * @date 2019/4/8 + *

+ * 码云登录 + */ +@Slf4j +@Component("GITEE") +@AllArgsConstructor +public class GiteeLoginHandler extends AbstractLoginHandler { + private final SysSocialDetailsMapper sysSocialDetailsMapper; + private final SysUserService sysUserService; + + + /** + * 码云登录传入code + *

+ * 通过code 调用qq 获取唯一标识 + * + * @param code + * @return + */ + @Override + public String identify(String code) { + SysSocialDetails condition = new SysSocialDetails(); + condition.setType(LoginTypeEnum.GITEE.getType()); + SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition)); + + String url = String.format(SecurityConstants.GITEE_AUTHORIZATION_CODE_URL, code + , socialDetails.getAppId(), URLUtil.encode(socialDetails.getRedirectUrl()), socialDetails.getAppSecret()); + String result = HttpUtil.post(url, new HashMap<>(0)); + log.debug("码云响应报文:{}", result); + + String accessToken = JSONUtil.parseObj(result).getStr("access_token"); + String userUrl = String.format(SecurityConstants.GITEE_USER_INFO_URL, accessToken); + String resp = HttpUtil.get(userUrl); + log.debug("码云获取个人信息返回报文{}", resp); + + JSONObject userInfo = JSONUtil.parseObj(resp); + //码云唯一标识 + String login = userInfo.getStr("login"); + return login; + } + + /** + * identify 获取用户信息 + * + * @param identify identify + * @return + */ + @Override + public UserInfo info(String identify) { + + + SysUser user = sysUserService + .getOne(Wrappers.query() + .lambda().eq(SysUser::getGiteeLogin, identify)); + + if (user == null) { + log.info("码云未绑定:{}", identify); + return null; + } + return sysUserService.findUserInfo(user); + } +} diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/OscChinaLoginHandler.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/OscChinaLoginHandler.java new file mode 100644 index 000000000..06a7a8f44 --- /dev/null +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/OscChinaLoginHandler.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.admin.handler; + +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.pig4cloud.pigx.admin.api.dto.UserInfo; +import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails; +import com.pig4cloud.pigx.admin.api.entity.SysUser; +import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper; +import com.pig4cloud.pigx.admin.service.SysUserService; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author lengleng + * @date 2019/4/8 + *

+ * 开源中国登录 + */ +@Slf4j +@Component("OSC") +@AllArgsConstructor +public class OscChinaLoginHandler extends AbstractLoginHandler { + private final SysSocialDetailsMapper sysSocialDetailsMapper; + private final SysUserService sysUserService; + + + /** + * 开源中国传入code + *

+ * 通过code 调用qq 获取唯一标识 + * + * @param code + * @return + */ + @Override + public String identify(String code) { + SysSocialDetails condition = new SysSocialDetails(); + condition.setType(LoginTypeEnum.OSC.getType()); + SysSocialDetails socialDetails = sysSocialDetailsMapper.selectOne(new QueryWrapper<>(condition)); + + Map params = new HashMap<>(8); + + params.put("client_id", socialDetails.getAppId()); + params.put("client_secret", socialDetails.getAppSecret()); + params.put("grant_type", "authorization_code"); + params.put("redirect_uri", socialDetails.getRedirectUrl()); + params.put("code", code); + params.put("dataType", "json"); + + String result = HttpUtil.post(SecurityConstants.OSC_AUTHORIZATION_CODE_URL, params); + log.debug("开源中国响应报文:{}", result); + + String accessToken = JSONUtil.parseObj(result).getStr("access_token"); + + String url = String.format(SecurityConstants.OSC_USER_INFO_URL, accessToken); + String resp = HttpUtil.get(url); + log.debug("开源中国获取个人信息返回报文{}", resp); + + JSONObject userInfo = JSONUtil.parseObj(resp); + //开源中国唯一标识 + String id = userInfo.getStr("id"); + return id; + } + + /** + * identify 获取用户信息 + * + * @param identify 开源中国表示 + * @return + */ + @Override + public UserInfo info(String identify) { + + + SysUser user = sysUserService + .getOne(Wrappers.query() + .lambda().eq(SysUser::getOscId, identify)); + + if (user == null) { + log.info("开源中国未绑定:{}", identify); + return null; + } + return sysUserService.findUserInfo(user); + } +} diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatLoginHandler.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatLoginHandler.java index b9c315bca..0164967e1 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatLoginHandler.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/handler/WeChatLoginHandler.java @@ -41,7 +41,6 @@ import org.springframework.web.client.RestTemplate; @Component("WX") @AllArgsConstructor public class WeChatLoginHandler extends AbstractLoginHandler { - private final RestTemplate restTemplate; private final SysUserService sysUserService; private final SysSocialDetailsMapper sysSocialDetailsMapper; diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysSocialDetailsServiceImpl.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysSocialDetailsServiceImpl.java index 1f17063eb..1cde0986e 100755 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysSocialDetailsServiceImpl.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/service/impl/SysSocialDetailsServiceImpl.java @@ -25,6 +25,7 @@ import com.pig4cloud.pigx.admin.handler.LoginHandler; import com.pig4cloud.pigx.admin.mapper.SysSocialDetailsMapper; import com.pig4cloud.pigx.admin.mapper.SysUserMapper; import com.pig4cloud.pigx.admin.service.SysSocialDetailsService; +import com.pig4cloud.pigx.common.core.constant.enums.LoginTypeEnum; import com.pig4cloud.pigx.common.security.util.SecurityUtils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -56,7 +57,15 @@ public class SysSocialDetailsServiceImpl extends ServiceImpl - ${project.name} + ${project.artifactId} src/main/resources