本地缓存用户token
This commit is contained in:
@ -13,3 +13,4 @@
|
||||
- add: 文件sdk新增修改文件名称接口 `cloud.attachment.sdk.api.AttachmentClient`
|
||||
- add: 新增角色-审查人员 `common.constant.EbtpRoleEnum`
|
||||
- update-20220630-fuqj:修改SpringSecurity过滤器中获取人员信息接口,调用extend服务,extend服务实现在山分接口基础上扩展本地角色信息。 `cloud.security.starter.filter.TokenAuthenticationFilter`
|
||||
- update-20220727-fuqj:修改获取人员信息逻辑,把从山分查询出来的人员通过extend服务扩展覆盖后的信息,缓存到本地redis中。
|
BIN
source/img.png
Normal file
BIN
source/img.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
@ -9,11 +9,15 @@ public interface Constants {
|
||||
public static final String TOKEN_PREFIX = "Bearer ";
|
||||
public static final String CURRENT_ROLE_CODE = "currentRoleCode";
|
||||
public static final String COOKIE_TOKEN_CODE = "mall3_token";
|
||||
public static final String REDIS_USER_KEY = "ebtp:user_cache:";
|
||||
public static final String REDIS_USER_KEY_EXTEND = "ebtp:user_cache_extend";
|
||||
public static final String USERS = "users";
|
||||
public static final String ROLES = "roles";
|
||||
|
||||
public static final String TOKEN_EXPIRED = "90401";
|
||||
public static final String REMOTE_ACCESS_FAILURE = "90500";
|
||||
|
||||
String ACTUATOR_HEALTH = "actuator/health";
|
||||
String ACTUATOR_PROMETHEUS = "actuator/prometheus";
|
||||
String GET_USERINFO_API = "/v1/userinfo/get";
|
||||
String GET_USERINFO_API = "/v1/userinfo/refresh";
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.security.starter.filter;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants;
|
||||
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.AuthAllows;
|
||||
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.RoleCodeAuthority;
|
||||
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.SecurityUser;
|
||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.client.EbtpUserInfoClient;
|
||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.service.UserInfoService;
|
||||
import com.chinaunicom.mall.ebtp.common.base.entity.BaseCacheUser;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -40,8 +40,6 @@ import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.
|
||||
public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||
@Autowired
|
||||
private UserInfoService client;
|
||||
@Autowired
|
||||
private EbtpUserInfoClient ebtpClient;
|
||||
|
||||
|
||||
@Autowired
|
||||
@ -101,6 +99,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
} catch (Exception e) {
|
||||
request.getSession().setAttribute("code", e.getMessage());
|
||||
ExceptionUtil.stacktraceToString(e);
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
@ -140,8 +139,8 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||
*/
|
||||
private Authentication getAuthentication(final String token, final String currentRoleCode,
|
||||
final boolean isWhite) {
|
||||
// BaseCacheUser userInfo = client.getUserInfo(token);
|
||||
BaseCacheUser userInfo = ebtpClient.get();
|
||||
BaseCacheUser userInfo = client.getUserInfo(token);
|
||||
// BaseCacheUser userInfo = ebtpClient.get();
|
||||
log.debug("getUserInfo:{}", userInfo.toString());
|
||||
// 对象为空, 则说明网络异常feign已熔断
|
||||
if (Objects.isNull(userInfo)) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.userinfo.starter.client;
|
||||
|
||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.fallback.EbtpUserInfoClientFallbackFactory;
|
||||
import com.chinaunicom.mall.ebtp.common.base.entity.BaseCacheUser;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
/**
|
||||
* 文档中心数据服务客户端
|
||||
@ -14,7 +14,11 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
fallbackFactory = EbtpUserInfoClientFallbackFactory.class)
|
||||
public interface EbtpUserInfoClient {
|
||||
|
||||
@GetMapping("/v1/userinfo/get")
|
||||
BaseCacheUser get();
|
||||
|
||||
/**
|
||||
* 刷新redis缓存的信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/v1/userinfo/refresh")
|
||||
public ResponseEntity<Boolean> refreshToken();
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.userinfo.starter.entity;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 功能模块bean
|
||||
*
|
||||
* @author zyx
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ApiModel
|
||||
public class CacheRole implements Serializable {
|
||||
|
||||
private static final Long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "角色")
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@ApiModelProperty(value = "备注")
|
||||
private String remarks;
|
||||
|
||||
/**
|
||||
* role_id
|
||||
*/
|
||||
@ApiModelProperty(value = "role_id")
|
||||
private String roleId;
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@ApiModelProperty(value = "状态,0-默认")
|
||||
private int status;
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.userinfo.starter.entity;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 功能模块bean
|
||||
*
|
||||
* @author zyx
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@ApiModel
|
||||
public class CacheUser implements Serializable {
|
||||
|
||||
private static final Long serialVersionUID = 1L;
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@ApiModelProperty(value = "编号")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
@ApiModelProperty(value = "姓名")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@ApiModelProperty(value = "账号")
|
||||
private String account;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@ApiModelProperty(value = "密码")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 省份
|
||||
*/
|
||||
@ApiModelProperty(value = "省份")
|
||||
private String province;
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*/
|
||||
@ApiModelProperty(value = "角色")
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* 租户
|
||||
*/
|
||||
@ApiModelProperty(value = "租户")
|
||||
private String tenant;
|
||||
}
|
@ -3,6 +3,7 @@ package com.chinaunicom.mall.ebtp.cloud.userinfo.starter.fallback;
|
||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.client.EbtpUserInfoClient;
|
||||
import feign.hystrix.FallbackFactory;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@ -12,6 +13,6 @@ public class EbtpUserInfoClientFallbackFactory implements FallbackFactory<EbtpUs
|
||||
@Override
|
||||
public EbtpUserInfoClient create(Throwable throwable) {
|
||||
log.error("EbtpUserInfoClient error : " + throwable.getMessage());
|
||||
return () -> null;
|
||||
return () -> ResponseEntity.ok(false);
|
||||
}
|
||||
}
|
||||
|
@ -3,23 +3,26 @@ package com.chinaunicom.mall.ebtp.cloud.userinfo.starter.service.impl;
|
||||
|
||||
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.AuthorityEntity;
|
||||
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.SecurityEntity;
|
||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.client.EbtpUserInfoClient;
|
||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.client.UnifastOAuthClient;
|
||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.entity.CacheRole;
|
||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.entity.CacheUser;
|
||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.service.UserInfoService;
|
||||
import com.chinaunicom.mall.ebtp.common.base.entity.BaseCacheUser;
|
||||
import com.chinaunicom.mall.ebtp.common.util.JsonUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.remoting.RemoteTimeoutException;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.REMOTE_ACCESS_FAILURE;
|
||||
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.TOKEN_EXPIRED;
|
||||
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -29,9 +32,83 @@ public class UserInfoServiceImpl implements UserInfoService {
|
||||
UnifastOAuthClient client;
|
||||
// private @Autowired ObjectMapper userInfoObjectMapper;
|
||||
|
||||
@Autowired(required = false)
|
||||
@Qualifier("cacheRedisTemplate")
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private EbtpUserInfoClient ebtpClient;
|
||||
|
||||
@Override
|
||||
public BaseCacheUser getUserInfo(String token) {
|
||||
return convertToBusinessModel(getAuthentication(token.replaceAll("Bearer ", "")));
|
||||
token = token.replaceAll(TOKEN_PREFIX, "");
|
||||
|
||||
Object o = redisTemplate.opsForValue().get(REDIS_USER_KEY + token);
|
||||
if (o == null) {
|
||||
return setLocalUserCache(token);
|
||||
}
|
||||
return (BaseCacheUser) o;
|
||||
}
|
||||
|
||||
/*
|
||||
* 本地缓存token
|
||||
*/
|
||||
private BaseCacheUser setLocalUserCache(String token) {
|
||||
|
||||
BaseCacheUser user = structureUser(token);
|
||||
|
||||
redisTemplate.opsForValue().set(REDIS_USER_KEY + token, user, 30, TimeUnit.MINUTES);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/*
|
||||
* 构建用户实体,查询extend缓存或服务覆盖用户信息。
|
||||
*/
|
||||
private BaseCacheUser structureUser(String token) {
|
||||
//查询山分用户信息
|
||||
BaseCacheUser user = convertToBusinessModel(getAuthentication(token));
|
||||
|
||||
//获取redis中extend的缓存
|
||||
Object extendRedis = redisTemplate.opsForValue().get(REDIS_USER_KEY_EXTEND);
|
||||
if (extendRedis == null) {
|
||||
//查extend库 刷新缓存
|
||||
ResponseEntity<Boolean> response = ebtpClient.refreshToken();
|
||||
if (response.getStatusCode().value() != 200 || Boolean.FALSE.equals(response.getBody())) {
|
||||
log.info("获取extend服务的user缓存失败");
|
||||
}
|
||||
extendRedis = redisTemplate.opsForValue().get(REDIS_USER_KEY_EXTEND);
|
||||
}
|
||||
|
||||
if (extendRedis == null) {
|
||||
return user;
|
||||
}
|
||||
|
||||
Map<String, String> userTable = JsonUtils.jsonToPojo(String.valueOf(extendRedis), Map.class);
|
||||
//获取用户信息
|
||||
List<CacheUser> users = JsonUtils.jsonToList(userTable.get(USERS), CacheUser.class);
|
||||
CacheUser baseUser = users.stream().filter(u -> u.getAccount().equals(user.getLoginName())).findFirst().orElse(null);
|
||||
if (Objects.isNull(baseUser)) {
|
||||
return user;
|
||||
}
|
||||
|
||||
List<CacheRole> roles = JsonUtils.jsonToList(userTable.get(ROLES), CacheRole.class);
|
||||
user.setProvince(baseUser.getProvince())
|
||||
//覆盖角色
|
||||
.setAuthorityList(
|
||||
Optional.of(roles
|
||||
.stream()
|
||||
.filter(r -> baseUser.getRole().contains(r.getRole()))
|
||||
.map(br ->
|
||||
new AuthorityEntity()
|
||||
.setRoleId(br.getRoleId())
|
||||
.setRoleCode(br.getRole())
|
||||
.setRoleName(br.getRemarks())
|
||||
.setRoleScope("EBTP")
|
||||
.setAuthorities(Collections.emptyList()))
|
||||
.collect(Collectors.toList()))
|
||||
.orElseGet(Collections::emptyList));
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,7 +118,7 @@ public class UserInfoServiceImpl implements UserInfoService {
|
||||
* @return
|
||||
*/
|
||||
private BaseCacheUser convertToBusinessModel(SecurityEntity raw) {
|
||||
log.debug("userinfo: {}", raw);
|
||||
log.info("userinfo: {}", raw);
|
||||
// 对象为空, 则说明网络异常feign已熔断
|
||||
if (Objects.isNull(raw)) {
|
||||
throw new RemoteTimeoutException(REMOTE_ACCESS_FAILURE);
|
||||
@ -94,6 +171,8 @@ public class UserInfoServiceImpl implements UserInfoService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
|
Reference in New Issue
Block a user