package com.persagy.account.controller; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.concurrent.TimeUnit; import org.apache.commons.collections4.map.HashedMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.alibaba.fastjson.JSONObject; import com.persagy.account.config.ApplicationProperties; import com.persagy.account.manage.SaasAuthHandler; import com.persagy.account.pojo.vo.thirty.SaasCodeTokenVO; import com.persagy.account.pojo.vo.thirty.SaasCodeVO; import com.persagy.common.constant.SaasCommonConstant; import com.persagy.common.enums.ResponseCode; import com.persagy.common.utils.ResponseResult; import com.persagy.common.utils.ResponseResultUtil; import com.persagy.common.utils.StringUtil; import com.persagy.security.util.BouncycastleCipher; import com.persagy.security.util.SecureAES; import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.crypto.digest.DigestAlgorithm; import cn.hutool.crypto.digest.MD5; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; /** * 三方授权中心 * @version 1.0.0 * @company persagy * @author zhangqiankun * @date 2021年4月27日 下午3:08:16 */ @RestController @Api(tags = "授权管理") @RequestMapping(value = "/authCenter", method = RequestMethod.POST) public class SaasAuthCenterController { private static MD5 md5 = MD5.create(); @Autowired private SaasAuthHandler saasAuthHandler; @Autowired private ApplicationProperties properties; //@Autowired //private ISaasAccountService saasAccountService; @Autowired private BouncycastleCipher bouncycastleCipher; @Autowired private RedisTemplate redisTemplate; /** * 申请授权码 */ @ApiOperation(value = "申请授权码") @RequestMapping(value = "code") public ResponseResult getCode(@RequestBody @Validated SaasCodeVO model) { String code = this.saasAuthHandler.getCode(model.getClientId(), model.getRedirectUrl(), null, null, null); Map result = new HashedMap(1); result.put("code", code); return ResponseResultUtil.successResult(result); } /** * 根据授权码获取token * @throws UnsupportedEncodingException */ @ApiOperation(value = "根据授权码获取token") @RequestMapping(value = "codeToken") public ResponseResult getCodeToken(@RequestBody @Validated SaasCodeTokenVO model) throws UnsupportedEncodingException { // 验证客户端ID是否存在 Boolean member = this.redisTemplate.opsForSet().isMember(SaasCommonConstant.SAAS_CLIENT_ID_REDIS_KEY, model.getClientId()); if (!BooleanUtil.isTrue(member)) { return ResponseResultUtil.errorResult(ResponseCode.A0001.getCode(), ResponseCode.A0001.getDesc()); } // 验证是否授权码存在 String code = (String) this.redisTemplate.opsForHash().get(model.getClientId(), SaasCommonConstant.CODE_REDIS_HASH_KEY); if (StringUtil.isBlank(code)) { return ResponseResultUtil.errorResult(ResponseCode.A0301.getCode(), ResponseCode.A0301.getDesc()); } if (!model.getCode().equals(code)) { return ResponseResultUtil.errorResult(ResponseCode.A0303.getCode(), ResponseCode.A0303.getDesc()); } // 判断token是否已存在 long expire = Long.parseLong(this.properties.getTokenExpire()); String accountId = (String) this.redisTemplate.opsForHash().get(model.getClientId(), SaasCommonConstant.ACCOUNT_ID_REDIS_HASH_KEY); if (StringUtil.isBlank(accountId)) { return ResponseResultUtil.errorResult(ResponseCode.A0402.getCode(), ResponseCode.A0402.getDesc()); } // token放入redis,key-accountId String token = (String) this.redisTemplate.opsForValue().get(accountId); if (StringUtil.isBlank(token)) { token = this.bouncycastleCipher.encrypt(this.getAccessToken(code), DigestAlgorithm.MD5); this.redisTemplate.opsForValue().set(accountId, token, expire, TimeUnit.SECONDS); } else { this.redisTemplate.expire(accountId, expire, TimeUnit.SECONDS); } // MD5生成 refreshToken,放进hash存储 String refreshToken = md5.digestHex(this.getRefreshToken()); this.redisTemplate.opsForHash().put(model.getClientId(), SaasCommonConstant.REFRESH_TOKEN_REDIS_HASH_KEY, refreshToken); // AES加密出账号信息所需字段,组合为token SecureAES aes = new SecureAES(properties.getAesKey(), properties.getAesIv()); String tokenPrefix = aes.encrypt(this.getTokenPrefix(model.getClientId(), accountId)); token = tokenPrefix + SaasCommonConstant.POINT_JOIN_SYMBOL + token; Map map = new HashedMap(); map.put("refreshToken", refreshToken); map.put("accessToken", token); map.put("expire", expire); return ResponseResultUtil.successResult(map); } /** * 这里的数据,均为登录时指定,为登录时指定的 * * @param clientId * @param accountId * @return */ private String getTokenPrefix(String clientId, String accountId) { String appId = (String) this.redisTemplate.opsForHash().get(clientId, SaasCommonConstant.APP_ID_REDIS_HASH_KEY); String groupCode = (String) this.redisTemplate.opsForHash().get(clientId, SaasCommonConstant.GROUP_CODE_REDIS_HASH_KEY); JSONObject result = new JSONObject(); result.put(SaasCommonConstant.ACCOUNT_ID, accountId); result.put(SaasCommonConstant.GROUP_CODE, groupCode); result.put(SaasCommonConstant.APP_ID, appId); return result.toJSONString(); } /** * 根据授权码组合token原信息 * @param code * @return */ private String getAccessToken(String code) { JSONObject object = new JSONObject(); object.put("code", code); return object.toJSONString(); } /** * 获取refreshToken * @param code * @return */ private String getRefreshToken() { JSONObject object = new JSONObject(); object.put("time", System.currentTimeMillis()); object.put("state", IdUtil.fastSimpleUUID()); return object.toJSONString(); } }