package com.deloitte.system.controller; import com.common.annotation.NoAuthorize; import com.common.annotation.NoToken; import com.common.annotation.RequestLimit; import com.common.core.beans.Result; import com.common.core.constant.GlobalConst; import com.common.core.enums.ResultCodeEnum; import com.common.core.exception.BizException; import com.common.core.utils.DistributedLock; import com.common.core.utils.JwtTokenUtil; import com.common.redis.util.RedisUtil; import com.common.security.configure.AppDetails; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * @author 廖振钦 * @date 2022-01-17 */ @Slf4j @RestController @RequestMapping("/token") public class TokenController { @Autowired private UserDetailsService userDetailsService; @Autowired private JwtTokenUtil jwtTokenUtil; @Autowired private RedisUtil redisUtil; @Autowired private DistributedLock distributedLock; @NoToken @NoAuthorize @RequestLimit(count = -1) @RequestMapping(value = "/getToken", method = RequestMethod.GET) public Result getToken(@RequestParam("app_id") String appId, @RequestParam("app_secret") String appSecret, @RequestParam(value = "user_id", required = false) String userid){ String token = null; Result res = Result.resp(ResultCodeEnum.RT_SUCCESS); String key=""; try { if(StringUtils.isEmpty(appSecret)){ throw new BadCredentialsException("appid, secret不正确"); } AppDetails userDetails = (AppDetails)userDetailsService.loadUserByUsername(appId); String password = userDetails.getPassword(); if (!appSecret.equals(password)) { throw new BadCredentialsException("appid, secret不正确"); } if(StringUtils.isNotEmpty(userid)) { userDetails.setUserid(userid); } Authentication authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); key=GlobalConst.TOKEN_KEY+appId; String keyTmp=GlobalConst.TOKEN_KEY_TMP+appId; if(StringUtils.isNotEmpty(userid)){ key +=":"+userid; keyTmp+=":"+userid; } Object tokenCache=redisUtil.get(key); long expire=redisUtil.getExpire(key); if(tokenCache!=null && StringUtils.isNotEmpty(tokenCache.toString())&& expire>GlobalConst.TOKEN_EXPIRE_BUFF){ token = tokenCache.toString(); } else { try { if (distributedLock.waitLock(key + ":lock", 300 * 1000)) { tokenCache = redisUtil.get(key); expire = redisUtil.getExpire(key); if (tokenCache != null && StringUtils.isNotEmpty(tokenCache.toString()) && expire > GlobalConst.TOKEN_EXPIRE_BUFF) { token = tokenCache.toString(); } else if (tokenCache != null && StringUtils.isNotEmpty(tokenCache.toString()) && expire <= GlobalConst.TOKEN_EXPIRE_BUFF) { token = jwtTokenUtil.generateToken(userDetails); redisUtil.set(key, token, GlobalConst.TOKEN_EXPIRE + GlobalConst.TOKEN_EXPIRE_BUFF); redisUtil.set(keyTmp, tokenCache.toString(), expire); } else { token = jwtTokenUtil.generateToken(userDetails); redisUtil.set(key, token, GlobalConst.TOKEN_EXPIRE + GlobalConst.TOKEN_EXPIRE_BUFF); } } } finally { distributedLock.releaseLock(key+":lock"); } } } catch (Exception e) { log.warn("登录异常:{}", e.getMessage()); throw new BizException(ResultCodeEnum.LOGIN_FAILED); } res.setObject(token); return res; } }