| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.jeecg.modules.system.controller; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.xkcoding.justauth.AuthRequestFactory; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import me.zhyd.oauth.model.AuthCallback; |
| | | import me.zhyd.oauth.model.AuthResponse; |
| | | import me.zhyd.oauth.request.AuthRequest; |
| | | import me.zhyd.oauth.utils.AuthStateUtils; |
| | | import org.jeecg.common.api.vo.Result; |
| | | import org.jeecg.common.constant.CommonConstant; |
| | | import org.jeecg.common.system.util.JwtUtil; |
| | | import org.jeecg.common.util.PasswordUtil; |
| | | import org.jeecg.common.util.RedisUtil; |
| | | import org.jeecg.common.util.RestUtil; |
| | | import org.jeecg.common.util.oConvertUtils; |
| | | import org.jeecg.config.thirdapp.ThirdAppConfig; |
| | | import org.jeecg.config.thirdapp.ThirdAppTypeItemVo; |
| | | import org.jeecg.modules.base.service.BaseCommonService; |
| | | import org.jeecg.modules.system.entity.SysThirdAccount; |
| | | import org.jeecg.modules.system.entity.SysUser; |
| | | import org.jeecg.modules.system.model.ThirdLoginModel; |
| | | import org.jeecg.modules.system.service.ISysThirdAccountService; |
| | | import org.jeecg.modules.system.service.ISysUserService; |
| | | import org.jeecg.modules.system.service.impl.ThirdAppDingtalkServiceImpl; |
| | | import org.jeecg.modules.system.service.impl.ThirdAppWechatEnterpriseServiceImpl; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Controller; |
| | | import org.springframework.ui.ModelMap; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.net.URLEncoder; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @Author scott |
| | | * @since 2018-12-17 |
| | | */ |
| | | @Controller |
| | | @RequestMapping("/sys/thirdLogin") |
| | | @Slf4j |
| | | public class ThirdLoginController { |
| | | @Autowired |
| | | private ISysUserService sysUserService; |
| | | @Autowired |
| | | private ISysThirdAccountService sysThirdAccountService; |
| | | |
| | | @Autowired |
| | | private BaseCommonService baseCommonService; |
| | | @Autowired |
| | | private RedisUtil redisUtil; |
| | | @Autowired |
| | | private AuthRequestFactory factory; |
| | | |
| | | @Autowired |
| | | ThirdAppConfig thirdAppConfig; |
| | | @Autowired |
| | | private ThirdAppWechatEnterpriseServiceImpl thirdAppWechatEnterpriseService; |
| | | @Autowired |
| | | private ThirdAppDingtalkServiceImpl thirdAppDingtalkService; |
| | | |
| | | @RequestMapping("/render/{source}") |
| | | public void render(@PathVariable("source") String source, HttpServletResponse response) throws IOException { |
| | | log.info("ç¬¬ä¸æ¹ç»å½è¿å
¥renderï¼" + source); |
| | | AuthRequest authRequest = factory.get(source); |
| | | String authorizeUrl = authRequest.authorize(AuthStateUtils.createState()); |
| | | log.info("ç¬¬ä¸æ¹ç»å½è®¤è¯å°åï¼" + authorizeUrl); |
| | | response.sendRedirect(authorizeUrl); |
| | | } |
| | | |
| | | @RequestMapping("/{source}/callback") |
| | | public String loginThird(@PathVariable("source") String source, AuthCallback callback,ModelMap modelMap) { |
| | | log.info("ç¬¬ä¸æ¹ç»å½è¿å
¥callbackï¼" + source + " paramsï¼" + JSONObject.toJSONString(callback)); |
| | | AuthRequest authRequest = factory.get(source); |
| | | AuthResponse response = authRequest.login(callback); |
| | | log.info(JSONObject.toJSONString(response)); |
| | | Result<JSONObject> result = new Result<JSONObject>(); |
| | | if(response.getCode()==2000) { |
| | | |
| | | JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(response.getData())); |
| | | String username = data.getString("username"); |
| | | String avatar = data.getString("avatar"); |
| | | String uuid = data.getString("uuid"); |
| | | //æé ç¬¬ä¸æ¹ç»å½ä¿¡æ¯åå¨å¯¹è±¡ |
| | | ThirdLoginModel tlm = new ThirdLoginModel(source, uuid, username, avatar); |
| | | //å¤æææ²¡æè¿ä¸ªäºº |
| | | //update-begin-author:wangshuai date:20201118 for:ä¿®æ¹ææ¥è¯¢ç¬¬ä¸æ¹è´¦æ·è¡¨ |
| | | LambdaQueryWrapper<SysThirdAccount> query = new LambdaQueryWrapper<SysThirdAccount>(); |
| | | query.eq(SysThirdAccount::getThirdUserUuid, uuid); |
| | | query.eq(SysThirdAccount::getThirdType, source); |
| | | List<SysThirdAccount> thridList = sysThirdAccountService.list(query); |
| | | SysThirdAccount user = null; |
| | | if(thridList==null || thridList.size()==0) { |
| | | //å¦åç´æ¥å建æ°è´¦å· |
| | | user = sysThirdAccountService.saveThirdUser(tlm); |
| | | }else { |
| | | //å·²åå¨ åªè®¾ç½®ç¨æ·å ä¸è®¾ç½®å¤´å |
| | | user = thridList.get(0); |
| | | } |
| | | // çætoken |
| | | //update-begin-author:wangshuai date:20201118 for:ä»ç¬¬ä¸æ¹ç»å½æ¥è¯¢æ¯å¦åå¨ç¨æ·idï¼ä¸åå¨ç»å®ææºå· |
| | | if(oConvertUtils.isNotEmpty(user.getSysUserId())) { |
| | | String sysUserId = user.getSysUserId(); |
| | | SysUser sysUser = sysUserService.getById(sysUserId); |
| | | String token = saveToken(sysUser); |
| | | modelMap.addAttribute("token", token); |
| | | }else{ |
| | | modelMap.addAttribute("token", "ç»å®ææºå·,"+""+uuid); |
| | | } |
| | | //update-end-author:wangshuai date:20201118 for:ä»ç¬¬ä¸æ¹ç»å½æ¥è¯¢æ¯å¦åå¨ç¨æ·idï¼ä¸åå¨ç»å®ææºå· |
| | | //update-begin--Author:wangshuai Date:20200729 forï¼æ¥å£å¨ç¾åæ ¡éªå¤±è´¥æ¶è¿åå¤±è´¥çæ è¯ç issues#1441-------------------- |
| | | }else{ |
| | | modelMap.addAttribute("token", "ç»å½å¤±è´¥"); |
| | | } |
| | | //update-end--Author:wangshuai Date:20200729 forï¼æ¥å£å¨ç¾åæ ¡éªå¤±è´¥æ¶è¿åå¤±è´¥çæ è¯ç issues#1441-------------------- |
| | | result.setSuccess(false); |
| | | result.setMessage("ç¬¬ä¸æ¹ç»å½å¼å¸¸,请è系管çå"); |
| | | return "thirdLogin"; |
| | | } |
| | | |
| | | /** |
| | | * å建æ°è´¦å· |
| | | * @param model |
| | | * @return |
| | | */ |
| | | @PostMapping("/user/create") |
| | | @ResponseBody |
| | | public Result<String> thirdUserCreate(@RequestBody ThirdLoginModel model) { |
| | | log.info("ç¬¬ä¸æ¹ç»å½å建æ°è´¦å·ï¼" ); |
| | | Result<String> res = new Result<>(); |
| | | Object operateCode = redisUtil.get(CommonConstant.THIRD_LOGIN_CODE); |
| | | if(operateCode==null || !operateCode.toString().equals(model.getOperateCode())){ |
| | | res.setSuccess(false); |
| | | res.setMessage("æ ¡éªå¤±è´¥"); |
| | | return res; |
| | | } |
| | | //å建æ°è´¦å· |
| | | //update-begin-author:wangshuai date:20201118 for:ä¿®æ¹æä»ç¬¬ä¸æ¹ç»å½æ¥åºæ¥çuser_idï¼å¨æ¥è¯¢ç¨æ·è¡¨å°½è¡token |
| | | SysThirdAccount user = sysThirdAccountService.saveThirdUser(model); |
| | | if(oConvertUtils.isNotEmpty(user.getSysUserId())){ |
| | | String sysUserId = user.getSysUserId(); |
| | | SysUser sysUser = sysUserService.getById(sysUserId); |
| | | // çætoken |
| | | String token = saveToken(sysUser); |
| | | //update-end-author:wangshuai date:20201118 for:ä¿®æ¹æä»ç¬¬ä¸æ¹ç»å½æ¥åºæ¥çuser_idï¼å¨æ¥è¯¢ç¨æ·è¡¨å°½è¡token |
| | | res.setResult(token); |
| | | res.setSuccess(true); |
| | | } |
| | | return res; |
| | | } |
| | | |
| | | /** |
| | | * ç»å®è´¦å· éè¦è®¾ç½®å¯ç éè¦èµ°ä¸éæ ¡éª |
| | | * @param json |
| | | * @return |
| | | */ |
| | | @PostMapping("/user/checkPassword") |
| | | @ResponseBody |
| | | public Result<String> checkPassword(@RequestBody JSONObject json) { |
| | | Result<String> result = new Result<>(); |
| | | Object operateCode = redisUtil.get(CommonConstant.THIRD_LOGIN_CODE); |
| | | if(operateCode==null || !operateCode.toString().equals(json.getString("operateCode"))){ |
| | | result.setSuccess(false); |
| | | result.setMessage("æ ¡éªå¤±è´¥"); |
| | | return result; |
| | | } |
| | | String username = json.getString("uuid"); |
| | | SysUser user = this.sysUserService.getUserByName(username); |
| | | if(user==null){ |
| | | result.setMessage("ç¨æ·æªæ¾å°"); |
| | | result.setSuccess(false); |
| | | return result; |
| | | } |
| | | String password = json.getString("password"); |
| | | String salt = user.getSalt(); |
| | | String passwordEncode = PasswordUtil.encrypt(user.getUsername(), password, salt); |
| | | if(!passwordEncode.equals(user.getPassword())){ |
| | | result.setMessage("å¯ç 䏿£ç¡®"); |
| | | result.setSuccess(false); |
| | | return result; |
| | | } |
| | | |
| | | sysUserService.updateById(user); |
| | | result.setSuccess(true); |
| | | // çætoken |
| | | String token = saveToken(user); |
| | | result.setResult(token); |
| | | return result; |
| | | } |
| | | |
| | | private String saveToken(SysUser user) { |
| | | // çætoken |
| | | String token = JwtUtil.sign(user.getUsername(), user.getPassword()); |
| | | redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); |
| | | // 设置è¶
æ¶æ¶é´ |
| | | redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000); |
| | | return token; |
| | | } |
| | | |
| | | /** |
| | | * ç¬¬ä¸æ¹ç»å½åè°æ¥å£ |
| | | * @param token |
| | | * @param thirdType |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | @RequestMapping(value = "/getLoginUser/{token}/{thirdType}", method = RequestMethod.GET) |
| | | @ResponseBody |
| | | public Result<JSONObject> getThirdLoginUser(@PathVariable("token") String token,@PathVariable("thirdType") String thirdType) throws Exception { |
| | | Result<JSONObject> result = new Result<JSONObject>(); |
| | | String username = JwtUtil.getUsername(token); |
| | | |
| | | //1. æ ¡éªç¨æ·æ¯å¦ææ |
| | | SysUser sysUser = sysUserService.getUserByName(username); |
| | | result = sysUserService.checkUserIsEffective(sysUser, null); |
| | | if(!result.isSuccess()) { |
| | | return result; |
| | | } |
| | | //update-begin-author:wangshuai date:20201118 for:妿çå®å§åå头åä¸åå¨å°±åç¬¬ä¸æ¹ç»å½ç |
| | | LambdaQueryWrapper<SysThirdAccount> query = new LambdaQueryWrapper<>(); |
| | | query.eq(SysThirdAccount::getSysUserId,sysUser.getId()); |
| | | query.eq(SysThirdAccount::getThirdType,thirdType); |
| | | SysThirdAccount account = sysThirdAccountService.getOne(query); |
| | | if(oConvertUtils.isEmpty(sysUser.getRealname())){ |
| | | sysUser.setRealname(account.getRealname()); |
| | | } |
| | | if(oConvertUtils.isEmpty(sysUser.getAvatar())){ |
| | | sysUser.setAvatar(account.getAvatar()); |
| | | } |
| | | //update-end-author:wangshuai date:20201118 for:妿çå®å§åå头åä¸åå¨å°±åç¬¬ä¸æ¹ç»å½ç |
| | | JSONObject obj = new JSONObject(); |
| | | //ç¨æ·ç»å½ä¿¡æ¯ |
| | | obj.put("userInfo", sysUser); |
| | | //token ä¿¡æ¯ |
| | | obj.put("token", token); |
| | | result.setResult(obj); |
| | | result.setSuccess(true); |
| | | result.setCode(200); |
| | | baseCommonService.addLog("ç¨æ·å: " + username + ",ç»å½æå[ç¬¬ä¸æ¹ç¨æ·]ï¼", CommonConstant.LOG_TYPE_1, null); |
| | | return result; |
| | | } |
| | | /** |
| | | * ç¬¬ä¸æ¹ç»å®ææºå·è¿åtoken |
| | | * |
| | | * @param jsonObject |
| | | * @return |
| | | */ |
| | | @ApiOperation("ææºå·ç»å½æ¥å£") |
| | | @PostMapping("/bindingThirdPhone") |
| | | @ResponseBody |
| | | public Result<String> bindingThirdPhone(@RequestBody JSONObject jsonObject) { |
| | | Result<String> result = new Result<String>(); |
| | | String phone = jsonObject.getString("mobile"); |
| | | String thirdUserUuid = jsonObject.getString("thirdUserUuid"); |
| | | // æ ¡éªéªè¯ç |
| | | String captcha = jsonObject.getString("captcha"); |
| | | //update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 ãæ¼æ´ãåç°æ°æ¼æ´å¾
å¤ç20220906 |
| | | String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+phone; |
| | | Object captchaCache = redisUtil.get(redisKey); |
| | | //update-end-author:taoyan date:2022-9-13 for: VUEN-2245 ãæ¼æ´ãåç°æ°æ¼æ´å¾
å¤ç20220906 |
| | | if (oConvertUtils.isEmpty(captcha) || !captcha.equals(captchaCache)) { |
| | | result.setMessage("éªè¯ç é误"); |
| | | result.setSuccess(false); |
| | | return result; |
| | | } |
| | | //æ ¡éªç¨æ·æææ§ |
| | | SysUser sysUser = sysUserService.getUserByPhone(phone); |
| | | if(sysUser != null){ |
| | | // åå¨ç¨æ·ï¼ç´æ¥ç»å® |
| | | sysThirdAccountService.updateThirdUserId(sysUser,thirdUserUuid); |
| | | }else{ |
| | | // ä¸å卿æºå·ï¼åå»ºç¨æ· |
| | | sysUser = sysThirdAccountService.createUser(phone,thirdUserUuid); |
| | | } |
| | | String token = saveToken(sysUser); |
| | | result.setSuccess(true); |
| | | result.setResult(token); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * ä¼ä¸å¾®ä¿¡/éé OAuth2ç»å½ |
| | | * |
| | | * @param source |
| | | * @param state |
| | | * @return |
| | | */ |
| | | @ResponseBody |
| | | @GetMapping("/oauth2/{source}/login") |
| | | public String oauth2LoginCallback(@PathVariable("source") String source, @RequestParam("state") String state, HttpServletResponse response) throws Exception { |
| | | String url; |
| | | if (ThirdAppConfig.WECHAT_ENTERPRISE.equalsIgnoreCase(source)) { |
| | | ThirdAppTypeItemVo config = thirdAppConfig.getWechatEnterprise(); |
| | | StringBuilder builder = new StringBuilder(); |
| | | // æé ä¼ä¸å¾®ä¿¡OAuth2ç»å½ææå°å |
| | | builder.append("https://open.weixin.qq.com/connect/oauth2/authorize"); |
| | | // ä¼ä¸çCorpID |
| | | builder.append("?appid=").append(config.getClientId()); |
| | | // ææåéå®åçåè°é¾æ¥å°åï¼è¯·ä½¿ç¨urlencode坹龿¥è¿è¡å¤ç |
| | | String redirectUri = RestUtil.getBaseUrl() + "/sys/thirdLogin/oauth2/wechat_enterprise/callback"; |
| | | builder.append("&redirect_uri=").append(URLEncoder.encode(redirectUri, "UTF-8")); |
| | | // è¿åç±»åï¼æ¤æ¶åºå®ä¸ºï¼code |
| | | builder.append("&response_type=code"); |
| | | // åºç¨ææä½ç¨åã |
| | | // snsapi_baseï¼é黿æï¼å¯è·åæåççåºç¡ä¿¡æ¯ï¼UserIdä¸DeviceIdï¼ï¼ |
| | | builder.append("&scope=snsapi_base"); |
| | | // éå®ååä¼å¸¦ä¸stateåæ°ï¼é¿åº¦ä¸å¯è¶
è¿128个åè |
| | | builder.append("&state=").append(state); |
| | | // ç»ç«¯ä½¿ç¨æ¤åæ°å¤ææ¯å¦éè¦å¸¦ä¸èº«ä»½ä¿¡æ¯ |
| | | builder.append("#wechat_redirect"); |
| | | url = builder.toString(); |
| | | } else if (ThirdAppConfig.DINGTALK.equalsIgnoreCase(source)) { |
| | | ThirdAppTypeItemVo config = thirdAppConfig.getDingtalk(); |
| | | StringBuilder builder = new StringBuilder(); |
| | | // æé ééOAuth2ç»å½ææå°å |
| | | builder.append("https://login.dingtalk.com/oauth2/auth"); |
| | | // ææéè¿/æç»ååè°å°åã |
| | | // 注æ éè¦ä¸æ³¨ååºç¨æ¶ç»è®°çååä¿æä¸è´ã |
| | | String redirectUri = RestUtil.getBaseUrl() + "/sys/thirdLogin/oauth2/dingtalk/callback"; |
| | | builder.append("?redirect_uri=").append(URLEncoder.encode(redirectUri, "UTF-8")); |
| | | // åºå®å¼ä¸ºcodeã |
| | | // ææéè¿åè¿åauthCodeã |
| | | builder.append("&response_type=code"); |
| | | // æ¥éª¤ä¸ä¸å建çåºç¨è¯¦æ
ä¸è·åã |
| | | // ä¼ä¸å
é¨åºç¨ï¼client_id为åºç¨çAppKeyã |
| | | builder.append("&client_id=").append(config.getClientId()); |
| | | // ææèå´ï¼ææé¡µé¢æ¾ç¤ºçææä¿¡æ¯ä»¥åºç¨æ³¨åæ¶é
ç½®ç为åã |
| | | // openidï¼ææåå¯è·å¾ç¨æ·userid |
| | | builder.append("&scope=openid"); |
| | | // è·éauthCodeåæ ·è¿åã |
| | | builder.append("&state=").append(state); |
| | | //update-begin---author:wangshuai ---date:20220613 forï¼[issues/I5BOUF]oauth2 ééæ æ³ç»å½------------ |
| | | builder.append("&prompt=").append("consent"); |
| | | //update-end---author:wangshuai ---date:20220613 forï¼[issues/I5BOUF]oauth2 ééæ æ³ç»å½-------------- |
| | | url = builder.toString(); |
| | | } else { |
| | | return "䏿¯æçsource"; |
| | | } |
| | | log.info("oauth2 login url:" + url); |
| | | response.sendRedirect(url); |
| | | return "loginâ¦"; |
| | | } |
| | | |
| | | /** |
| | | * ä¼ä¸å¾®ä¿¡/éé OAuth2ç»å½åè° |
| | | * |
| | | * @param code |
| | | * @param state |
| | | * @param response |
| | | * @return |
| | | */ |
| | | @ResponseBody |
| | | @GetMapping("/oauth2/{source}/callback") |
| | | public String oauth2LoginCallback( |
| | | @PathVariable("source") String source, |
| | | // ä¼ä¸å¾®ä¿¡è¿åçcode |
| | | @RequestParam(value = "code", required = false) String code, |
| | | // ééè¿åçcode |
| | | @RequestParam(value = "authCode", required = false) String authCode, |
| | | @RequestParam("state") String state, |
| | | HttpServletResponse response) { |
| | | SysUser loginUser; |
| | | if (ThirdAppConfig.WECHAT_ENTERPRISE.equalsIgnoreCase(source)) { |
| | | log.info("ãä¼ä¸å¾®ä¿¡ãOAuth2ç»å½è¿å
¥callbackï¼code=" + code + ", state=" + state); |
| | | loginUser = thirdAppWechatEnterpriseService.oauth2Login(code); |
| | | if (loginUser == null) { |
| | | return "ç»å½å¤±è´¥"; |
| | | } |
| | | } else if (ThirdAppConfig.DINGTALK.equalsIgnoreCase(source)) { |
| | | log.info("ãééãOAuth2ç»å½è¿å
¥callbackï¼authCode=" + authCode + ", state=" + state); |
| | | loginUser = thirdAppDingtalkService.oauth2Login(authCode); |
| | | if (loginUser == null) { |
| | | return "ç»å½å¤±è´¥"; |
| | | } |
| | | } else { |
| | | return "䏿¯æçsource"; |
| | | } |
| | | try { |
| | | |
| | | //update-begin-author:taoyan date:2022-6-30 for: 工使µåéæ¶æ¯ ç¹å»æ¶æ¯é¾æ¥è·³è½¬åçé¡µé¢ |
| | | String redirect = ""; |
| | | if (state.indexOf("?") > 0) { |
| | | String[] arr = state.split("\\?"); |
| | | state = arr[0]; |
| | | if(arr.length>1){ |
| | | redirect = arr[1]; |
| | | } |
| | | } |
| | | |
| | | String token = saveToken(loginUser); |
| | | state += "/oauth2-app/login?oauth2LoginToken=" + URLEncoder.encode(token, "UTF-8"); |
| | | //update-begin---author:wangshuai ---date:20220613 forï¼[issues/I5BOUF]oauth2 ééæ æ³ç»å½------------ |
| | | state += "&thirdType=" + source; |
| | | //state += "&thirdType=" + "wechat_enterprise"; |
| | | if (redirect != null && redirect.length() > 0) { |
| | | state += "&" + redirect; |
| | | } |
| | | //update-end-author:taoyan date:2022-6-30 for: 工使µåéæ¶æ¯ ç¹å»æ¶æ¯é¾æ¥è·³è½¬åçé¡µé¢ |
| | | |
| | | //update-end---author:wangshuai ---date:20220613 forï¼[issues/I5BOUF]oauth2 ééæ æ³ç»å½------------ |
| | | log.info("OAuth2ç»å½éå®åå°å: " + state); |
| | | try { |
| | | response.sendRedirect(state); |
| | | return "ok"; |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | return "éå®å失败"; |
| | | } |
| | | } catch (UnsupportedEncodingException e) { |
| | | e.printStackTrace(); |
| | | return "è§£ç 失败"; |
| | | } |
| | | } |
| | | |
| | | } |