ludc
2023-09-17 fbdbcfab736a7d6ed18e032ed65cf981bbc50ee9
Source/UBCS/ubcs-service/ubcs-code/src/main/java/com/vci/ubcs/code/service/impl/PasswordFreeLoginServiceImpl.java
@@ -1,14 +1,21 @@
package com.vci.ubcs.code.service.impl;
import com.alibaba.fastjson.JSON;
import com.vci.ubcs.code.config.HeaderMapRequestWrapper;
import com.vci.ubcs.code.entity.TokenUserObject;
import com.vci.ubcs.code.service.IPasswordFreeLoginService;
import com.vci.ubcs.code.util.HttpUtils;
import org.springblade.core.cache.utils.CacheUtil;
import io.jsonwebtoken.Claims;
import org.apache.http.auth.AuthenticationException;
import org.springblade.core.jwt.JwtUtil;
import org.springblade.core.jwt.props.JwtProperties;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.ObjectUtil;
import org.springblade.core.tool.utils.SpringUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
@@ -19,11 +26,12 @@
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import static org.springblade.core.secure.utils.AuthUtil.parseJWT;
/**
 * 免密登录服务
@@ -42,64 +50,20 @@
   private BladeRedis bladeRedis;
   // 缓存名
   public static final String PWD_FREE_LOGIN_TOKEN = "pwdFreeLogin:Token:";
   private static JwtProperties jwtProperties;
   /**
    * 获取网关端口
    * 根据服务名获取端口号
    * @param serviceId
    * @return
    */
   private String getGatewayPort() {
      List<ServiceInstance> instances = discoveryClient.getInstances("ubcs-gateway");
   public String getGatewayPort(String serviceId) {
      List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
      if (!instances.isEmpty()) {
         ServiceInstance gatewayInstance = instances.get(0);
         return String.valueOf(gatewayInstance.getPort());
      }
      return "80";
   }
   /**
    * 免密登录并存入缓存,配合过滤器写法
    * @param username 账号
    * @return
    */
   @Override
   public String passwordFreeLogin(String username, ServletRequest servletRequest) {
      // 免密登录接口地址
      String loginUrl = "http://localhost:"+this.getGatewayPort()+"/ubcs-auth/oauth/token";
      // 请求来自己哪个ip地址
      HttpServletRequest request = (HeaderMapRequestWrapper) servletRequest;
      String ipAddr = request.getRemoteAddr();
      // 先尝试从缓存当中取,如果不存在就登录
      String redisToken = (String)bladeRedis.get(PWD_FREE_LOGIN_TOKEN+ipAddr);
      if(Func.isNotBlank(redisToken)){
         // 缓存中已经存在就直接删除该缓存,主要为了避免统一ip下存在多个token的情况
         bladeRedis.del(PWD_FREE_LOGIN_TOKEN+ipAddr);
      }
      // 不存在就重新获取token
      // 设置请求头
      HttpHeaders headers = new HttpHeaders();
      headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
      headers.set("Authorization", "Basic c3dvcmQ6c3dvcmRfc2VjcmV0");
      headers.set("Tenant-Id", pwdFreeTenantId);
      //设置请求体参数
      MultiValueMap<String,String> parameters = new LinkedMultiValueMap<String,String>();
      parameters.add("username",username);
      parameters.add("grant_type", "passwordfree");
      parameters.add("scope", "all");
      parameters.add("type", "account");
      // 发送POST请求
      String responseBody = HttpUtils.post(loginUrl, parameters,headers);
      //拿到响应体其中包含token,用request中的ip地址作为键值,将token存入缓存
      TokenUserObject tokenUserObject = null;
      try {
         tokenUserObject = JSON.parseObject(responseBody, TokenUserObject.class);
      }catch (Exception e){
         throw new ServiceException("responseBody转换TokenUserObject失败:"+e.getMessage());
      }
      // 将token存入缓存当中,过期时间为24小时
      bladeRedis.setEx(PWD_FREE_LOGIN_TOKEN+ipAddr,"bearer "+tokenUserObject.getAccess_token(),60*60*60*24L);
      return responseBody;
      return "8080";
   }
   /**
@@ -108,41 +72,139 @@
    * @return
    */
   @Override
   public boolean passwordFreeLogin2(String username, HttpServletRequest servletRequest) {
      // 免密登录接口地址
      String loginUrl = "http://localhost:"+this.getGatewayPort()+"/ubcs-auth/oauth/token";
      // 获取token,先设置请求头
      HttpHeaders headers = new HttpHeaders();
      headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
      headers.set("Authorization", "Basic c3dvcmQ6c3dvcmRfc2VjcmV0");
      headers.set("Tenant-Id", pwdFreeTenantId);
      //设置请求体参数
      MultiValueMap<String,String> parameters = new LinkedMultiValueMap<String,String>();
      parameters.add("username",username);
      parameters.add("grant_type", "passwordfree");
      parameters.add("scope", "all");
      parameters.add("type", "account");
      // 发送POST请求
      String responseBody = HttpUtils.post(loginUrl, parameters,headers);
      //拿到响应体其中包含token,用request中的ip地址作为键值,将token存入缓存
      TokenUserObject tokenUserObject = null;
      try {
         tokenUserObject = JSON.parseObject(responseBody, TokenUserObject.class);
      }catch (Exception e){
         throw new ServiceException("responseBody转换TokenUserObject失败:"+e.getMessage());
   public boolean passwordFreeLogin(String username, ServletRequest servletRequest) throws AuthenticationException {
      //进来先判断缓存中是否存在token
      // 请求来自己哪个ip地址
      HttpServletRequest request = (HttpServletRequest) servletRequest;
      String ipAddr = request.getRemoteAddr();
      // 先尝试从缓存当中取,存在就直接从缓存中获取
      String authToken = bladeRedis.get(PWD_FREE_LOGIN_TOKEN+ipAddr);
      BladeUser user = null;
      //不存在就请求
      if(Func.isEmpty(authToken)){
         // 免密登录接口地址
         String loginUrl = "http://localhost:"+this.getGatewayPort("ubcs-gateway")+"/ubcs-auth/oauth/token";
         // 请求ubcs-auth服务获取token,先设置请求头
         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
         headers.set("Authorization", "Basic c3dvcmQ6c3dvcmRfc2VjcmV0");
         headers.set("Tenant-Id", pwdFreeTenantId);
         //设置请求体参数
         MultiValueMap<String,String> parameters = new LinkedMultiValueMap<String,String>();
         parameters.add("username",username);
         parameters.add("grant_type", "passwordfree");
         parameters.add("scope", "all");
         parameters.add("type", "account");
         String responseBody = null;
         try {
            // 发送POST请求
            responseBody = HttpUtils.post(loginUrl, parameters,headers);
         }catch (Exception e){
            throw new AuthenticationException("调用鉴权服务ubcs-auth失败,原因:"+e.getMessage());
         }
         //拿到响应体其中包含token,用request中的ip地址作为键值,将token存入缓存
         TokenUserObject tokenUserObject = null;
         try {
            tokenUserObject = JSON.parseObject(responseBody, TokenUserObject.class);
         }catch (Exception e){
            throw new ServiceException("鉴权响应内容转换为TokenUserObject失败:"+e.getMessage());
         }
         // 拼接token格式
         authToken = "bearer " + tokenUserObject.getAccess_token();
         // 将token存入缓存当中,过期时间为24小时
         bladeRedis.setEx(PWD_FREE_LOGIN_TOKEN+ipAddr,"bearer "+tokenUserObject.getAccess_token(),60*60*60*24L);
      }
      HttpServletRequest request = (HeaderMapRequestWrapper) servletRequest;
      HeaderMapRequestWrapper requestWrapper = new HeaderMapRequestWrapper(request);
      //设置当前web接口的请求头
      String token = "bearer " + tokenUserObject.getAccess_token();
      // 将token设置到header中
      requestWrapper.setHeader("Blade-Auth", token);
      requestWrapper.setHeader("Authorization","Basic c3dvcmQ6c3dvcmRfc2VjcmV0");
      // 将token存入缓存当中,过期时间为24小时
      // 解析token存放进attr中
      String token2 = JwtUtil.getToken(authToken);
      user = this.getUser(token2);
      //request.setAttribute("Blade-Auth",token);
      request.setAttribute("_BLADE_USER_REQUEST_ATTR_",user);
      return true;
   }
   /**
    * 根据token获取用户信息
    * @param token
    * @return
    */
   private static BladeUser getUser(String token) {
      Claims claims = getClaims(token);
      if (claims == null) {
         return null;
      } else {
         String clientId = Func.toStr(claims.get("client_id"));
         Long userId = Func.toLong(claims.get("user_id"));
         String tenantId = Func.toStr(claims.get("tenant_id"));
         String oauthId = Func.toStr(claims.get("oauth_id"));
         String deptId = Func.toStrWithEmpty(claims.get("dept_id"), "-1");
         String postId = Func.toStrWithEmpty(claims.get("post_id"), "-1");
         String roleId = Func.toStrWithEmpty(claims.get("role_id"), "-1");
         String account = Func.toStr(claims.get("account"));
         String roleName = Func.toStr(claims.get("role_name"));
         String userName = Func.toStr(claims.get("user_name"));
         String nickName = Func.toStr(claims.get("nick_name"));
         String tenantName = Func.toStr(claims.get("tenantName"));
         String email = Func.toStr(claims.get("email"));
         String deptName = Func.toStr(claims.get("deptName"));
         String secretGrade = Func.toStr(claims.get("secretGrade"));
         Kv detail = Kv.create().setAll((Map)claims.get("detail"));
         BladeUser bladeUser = new BladeUser();
         bladeUser.setClientId(clientId);
         bladeUser.setUserId(userId);
         bladeUser.setTenantId(tenantId);
         bladeUser.setOauthId(oauthId);
         bladeUser.setAccount(account);
         bladeUser.setDeptId(deptId);
         bladeUser.setPostId(postId);
         bladeUser.setRoleId(roleId);
         bladeUser.setRoleName(roleName);
         bladeUser.setUserName(userName);
         bladeUser.setNickName(nickName);
         detail.put("tenantName", tenantName);
         detail.put("deptName", deptName);
         detail.put("email", email);
         detail.put("secretGrade", secretGrade);
         bladeUser.setDetail(detail);
         return bladeUser;
      }
   }
   /**
    * 解析token
    * @param authToken
    * @return
    */
   private static Claims getClaims(String authToken) {
      Claims claims = null;
      String token = null;
      String tenantId;
      if (StringUtil.isNotBlank(authToken)) {
         token = JwtUtil.getToken(authToken);
      }
      if (StringUtil.isNotBlank(token)) {
         claims = parseJWT(token);
      }
      if (ObjectUtil.isNotEmpty(claims) && getJwtProperties().getState()) {
         tenantId = Func.toStr(claims.get("tenant_id"));
         String userId = Func.toStr(claims.get("user_id"));
         String accessToken = JwtUtil.getAccessToken(tenantId, userId, token);
         if (!token.equalsIgnoreCase(accessToken)) {
            return null;
         }
      }
      return claims;
   }
   private static JwtProperties getJwtProperties() {
      if (jwtProperties == null) {
         jwtProperties = (JwtProperties) SpringUtil.getBean(JwtProperties.class);
      }
      return jwtProperties;
   }
}