Merge remote-tracking branch 'efren/master' into efren-dev
This commit is contained in:
@ -16,6 +16,12 @@
|
|||||||
<name>uboot-common</name>
|
<name>uboot-common</name>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-core</artifactId>
|
||||||
|
<version>5.7.3</version> <!-- 按需调整版本 -->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
<!-- <groupId>com.chinaunicom.ebtp</groupId>-->
|
<!-- <groupId>com.chinaunicom.ebtp</groupId>-->
|
||||||
<!-- <artifactId>mall-ebtp-cloud-jpa-starter</artifactId>-->
|
<!-- <artifactId>mall-ebtp-cloud-jpa-starter</artifactId>-->
|
||||||
@ -116,7 +122,7 @@
|
|||||||
<artifactId>poi-ooxml-schemas</artifactId>
|
<artifactId>poi-ooxml-schemas</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--security-->
|
<!-- <!–security–>-->
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
<!-- <groupId>org.springframework.cloud</groupId>-->
|
<!-- <groupId>org.springframework.cloud</groupId>-->
|
||||||
<!-- <artifactId>spring-cloud-security</artifactId>-->
|
<!-- <artifactId>spring-cloud-security</artifactId>-->
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.chinaunicom.mall.ebtp.cloud.security.starter.entity;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于角色的权限信息
|
||||||
|
*
|
||||||
|
* @author Ajaxfan
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class RoleCodeAuthority implements GrantedAuthority {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -7881153326775335008L;
|
||||||
|
|
||||||
|
private String roleCode;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthority() {
|
||||||
|
return roleCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.chinaunicom.mall.ebtp.cloud.security.starter.filter;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class BearerTokenFilter implements Filter {
|
||||||
|
private static final String AUTHORIZATION_HEADER = "Authorization";
|
||||||
|
private static final String BEARER_PREFIX = "Bearer ";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
|
try {
|
||||||
|
if (request instanceof HttpServletRequest) {
|
||||||
|
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||||
|
String authHeader = httpRequest.getHeader(AUTHORIZATION_HEADER);
|
||||||
|
if (authHeader != null && authHeader.startsWith(BEARER_PREFIX)) {
|
||||||
|
String token = authHeader.substring(BEARER_PREFIX.length());
|
||||||
|
BearerTokenHolder.setToken(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
} finally {
|
||||||
|
BearerTokenHolder.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.chinaunicom.mall.ebtp.cloud.security.starter.filter;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class BearerTokenFilterConfig {
|
||||||
|
@Bean
|
||||||
|
public FilterRegistrationBean<BearerTokenFilter> bearerTokenFilterRegistration() {
|
||||||
|
FilterRegistrationBean<BearerTokenFilter> registration = new FilterRegistrationBean<>();
|
||||||
|
registration.setFilter(new BearerTokenFilter());
|
||||||
|
registration.addUrlPatterns("/*");
|
||||||
|
registration.setName("bearerTokenFilter");
|
||||||
|
registration.setOrder(-100); // 优先级高于 Spring Security
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.chinaunicom.mall.ebtp.cloud.security.starter.filter;
|
||||||
|
|
||||||
|
public class BearerTokenHolder {
|
||||||
|
private static final ThreadLocal<String> TOKEN_HOLDER = new ThreadLocal<>();
|
||||||
|
|
||||||
|
public static void setToken(String token) {
|
||||||
|
TOKEN_HOLDER.set(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getToken() {
|
||||||
|
return TOKEN_HOLDER.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
TOKEN_HOLDER.remove();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,325 @@
|
|||||||
|
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.common.RSAcheck;
|
||||||
|
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.AuthAllows;
|
||||||
|
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.ExternalAllows;
|
||||||
|
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.entity.CheckTokenVo;
|
||||||
|
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.exception.common.CommonExceptionEnum;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.RegExUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.remoting.RemoteTimeoutException;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求Token拦截
|
||||||
|
*
|
||||||
|
* @author Ajaxfan
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
@Autowired
|
||||||
|
private UserInfoService client;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthAllows allows;
|
||||||
|
@Autowired
|
||||||
|
private ExternalAllows eAllows;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EbtpUserInfoClient ebtpClient;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
@Qualifier("userinfoRedisTemplate")
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
/**
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @param filterChain
|
||||||
|
* @throws ServletException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
|
||||||
|
final FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
//解密 恢复请求参数
|
||||||
|
//ParameterRequestWrapper requestWrapper = new ParameterRequestWrapper((HttpServletRequest) request,privateKey);
|
||||||
|
|
||||||
|
String api = request.getRequestURI();
|
||||||
|
String method = request.getMethod();
|
||||||
|
if (!StringUtils.contains(api, ACTUATOR_PROMETHEUS)) {
|
||||||
|
log.info("--------" + method + " - " + api + "?" + Optional.ofNullable(request.getQueryString()).orElse(""));
|
||||||
|
}
|
||||||
|
//String check_header = request.getHeader(HEADER_CHECK_TOKEN);
|
||||||
|
if(api.contains(CHECK_TOKEN_CONFIG)){
|
||||||
|
isNullThenAssignDefault();
|
||||||
|
// 过滤链调用
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckTokenVo checkTokenVo = client.getCheckTokenByRedis();
|
||||||
|
|
||||||
|
//校验是否是fegin请求
|
||||||
|
String isFeginKey = request.getHeader("isFegin");
|
||||||
|
String isFegin = null;
|
||||||
|
if(isFeginKey!=null&&!"".equals(isFeginKey)) {
|
||||||
|
try {
|
||||||
|
isFegin = RSAcheck.decrypt(isFeginKey, checkTokenVo.getCheckprivateKey());//checkprivateKey
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("isFegin 解密异常", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 清空上下文中的缓存信息, 防止二次请求时数据异常 (如此, 每次有新的请求进入,都会进行token的验证)
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(null);
|
||||||
|
|
||||||
|
boolean isWhite = checkWhiteList(api, method);
|
||||||
|
if (isWhite) {
|
||||||
|
isNullThenAssignDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_USERINFO_API.equals(api)) {
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取request头信息
|
||||||
|
final String header = request.getHeader(AUTHORIZATION_HEADER);
|
||||||
|
final String currentRoleCode = request.getHeader(CURRENT_ROLE_CODE);
|
||||||
|
log.debug("header:{},currentRoleCode:{}", header, currentRoleCode);
|
||||||
|
Boolean tokenCheckB = false;
|
||||||
|
try {
|
||||||
|
|
||||||
|
// 检查请求头是否包含 Bearer 前缀
|
||||||
|
if (StringUtils.startsWith(header, Constants.TOKEN_PREFIX)) {
|
||||||
|
setAuthentication(currentRoleCode, RegExUtils.replaceAll(header, Constants.TOKEN_PREFIX, ""), isWhite);// 移除header的前缀,提取出token字串
|
||||||
|
tokenCheckB = true;
|
||||||
|
}
|
||||||
|
// 检查cookie
|
||||||
|
// else {
|
||||||
|
// Optional<Cookie> optionalCookie = Optional.ofNullable(request.getCookies())
|
||||||
|
// .flatMap(cookies ->
|
||||||
|
// Stream.of(cookies)
|
||||||
|
// .filter(item -> StringUtils.equals(item.getName(), COOKIE_TOKEN_CODE))
|
||||||
|
// .findFirst());
|
||||||
|
// if (optionalCookie.isPresent()) {
|
||||||
|
// setAuthentication(currentRoleCode, optionalCookie.get().getValue(), isWhite);
|
||||||
|
// } else if (!api.contains(ACTUATOR_HEALTH) && !api.contains(ACTUATOR_PROMETHEUS)) {
|
||||||
|
// log.warn("cookie中没有token信息:{}", api);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
request.getSession().setAttribute("code", e.getMessage());
|
||||||
|
ExceptionUtil.stacktraceToString(e);
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isExternal = externalCheckWhiteList(api, method);
|
||||||
|
log.info(api+"|"+isExternal);
|
||||||
|
//校验token 时间戳
|
||||||
|
if(tokenCheckB&&!isExternal&&!isWhite) {
|
||||||
|
if (!api.contains(ACTUATOR_HEALTH) && !api.contains(ACTUATOR_PROMETHEUS)
|
||||||
|
&& (isFegin == null || !"isFegin".equals(isFegin))) {
|
||||||
|
BaseCacheUser buser = new BaseCacheUser();
|
||||||
|
BeanUtils.copyProperties(SecurityContextHolder.getContext().getAuthentication().getPrincipal(), buser);
|
||||||
|
log.info("获取用户信息:" + buser);
|
||||||
|
if (buser != null && buser.getUserId() != null && !"".equals(buser.getUserId())) {
|
||||||
|
if (!checkTokenTime(request, response, filterChain,checkTokenVo)) {
|
||||||
|
request.getSession().setAttribute("code", "90501");
|
||||||
|
CommonExceptionEnum.FRAME_EXCEPTION_COMMON_DATA_OTHER_ERROR.customValidName("无效请求", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤链调用
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验请求唯一性
|
||||||
|
* @param request
|
||||||
|
*/
|
||||||
|
public Boolean checkTokenTime(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain,CheckTokenVo checkTokenVo){
|
||||||
|
|
||||||
|
Boolean b = true;
|
||||||
|
String check_header = request.getHeader(HEADER_CHECK_TOKEN);
|
||||||
|
log.info("request check_header:"+check_header);
|
||||||
|
if("1".equals(checkTokenVo.getOnof())){//onof
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_header!=null&&!"".equals(check_header)) {
|
||||||
|
String cookieKey = check_header;//optionalCookie.get().getValue();
|
||||||
|
log.info("cookieKey:"+cookieKey);
|
||||||
|
Object o = redisTemplate.opsForValue().get(HEADER_CHECK_TOKEN+":"+cookieKey);
|
||||||
|
if (o != null) {
|
||||||
|
String num = String.valueOf(o);
|
||||||
|
log.info(HEADER_CHECK_TOKEN+":"+cookieKey+"= "+num);
|
||||||
|
if("2".equals(num)){
|
||||||
|
log.error("请求连接已使用过");
|
||||||
|
b = false;
|
||||||
|
}else{
|
||||||
|
redisTemplate.opsForValue().set(HEADER_CHECK_TOKEN+":"+cookieKey, 2, 5, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
redisTemplate.opsForValue().set(HEADER_CHECK_TOKEN+":"+cookieKey, 1, 5, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
String header = request.getHeader(AUTHORIZATION_HEADER);//请求头token
|
||||||
|
header = RegExUtils.replaceAll(header, Constants.TOKEN_PREFIX, "");
|
||||||
|
Object cacheUser = redisTemplate.opsForValue().get(REDIS_USER_KEY + header);
|
||||||
|
if (cacheUser == null) {
|
||||||
|
log.error("请求已超时");
|
||||||
|
b = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// String cookieValue = "";
|
||||||
|
// try {
|
||||||
|
// cookieValue = RSAcheck.decrypt(cookieKey, checkTokenVo.getCheckprivateKey());//checkprivateKey
|
||||||
|
// }catch (Exception e){
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// log.info("header :"+header);
|
||||||
|
// log.info("cookieValue :"+cookieValue);
|
||||||
|
// String[] checkValues = String.valueOf(cookieValue).split("_");//0 token 1 token 时间
|
||||||
|
// if (!header.equals(checkValues[0])) {
|
||||||
|
// log.error("请求连接token不一致");
|
||||||
|
// b = false;
|
||||||
|
// }
|
||||||
|
// //SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
// long newDateLong = System.currentTimeMillis();
|
||||||
|
// long inDateLong = Long.valueOf(checkValues[1]).longValue();
|
||||||
|
//
|
||||||
|
//// log.info("newDateLong:"+newDateLong);
|
||||||
|
//// log.info("inDateLong:"+inDateLong);
|
||||||
|
//// log.info("kswTimeLimit:"+checkTokenVo.getTimeLimit());//kswTimeLimit
|
||||||
|
//// log.info("newDateLong - inDateLong :"+(newDateLong - inDateLong));
|
||||||
|
//// log.info("newDateLong - inDateLong 结果 :"+((newDateLong - inDateLong) > Long.valueOf(checkTokenVo.getTimeLimit()).longValue()));
|
||||||
|
// if ((newDateLong - inDateLong) > Long.valueOf(checkTokenVo.getTimeLimit()).longValue()) {//
|
||||||
|
// log.error("请求已超时");
|
||||||
|
// b = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.error("请求未授权");
|
||||||
|
b = false;
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 白名单验证
|
||||||
|
*
|
||||||
|
* @param method url地址
|
||||||
|
* @param methodType 请求方式 GET
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean checkWhiteList(String method, String methodType) {
|
||||||
|
return Optional.ofNullable(allows.getApis()).orElseGet(ArrayList::new)
|
||||||
|
.parallelStream().anyMatch(reg -> Pattern.compile(reg).matcher(methodType + "." + method).matches())
|
||||||
|
|| method.contains(ACTUATOR_HEALTH) //服务的就绪检测
|
||||||
|
|| method.contains(ACTUATOR_PROMETHEUS) //prometheus检测
|
||||||
|
|| method.contains(GET_USERINFO_API); //获取用户信息接口
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 外部接口白名单验证
|
||||||
|
*
|
||||||
|
* @param method url地址
|
||||||
|
* @param methodType 请求方式 GET
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean externalCheckWhiteList(String method, String methodType) {
|
||||||
|
return Optional.ofNullable(eAllows.getApis()).orElseGet(ArrayList::new)
|
||||||
|
.parallelStream().anyMatch(reg -> Pattern.compile(reg).matcher(methodType + "." + method).matches())
|
||||||
|
|| method.contains(ACTUATOR_HEALTH) //服务的就绪检测
|
||||||
|
|| method.contains(ACTUATOR_PROMETHEUS) //prometheus检测
|
||||||
|
|| method.contains(GET_USERINFO_API); //获取用户信息接口
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置认证用户信息
|
||||||
|
*
|
||||||
|
* @param currentRoleCode
|
||||||
|
* @param authToken
|
||||||
|
*/
|
||||||
|
private void setAuthentication(final String currentRoleCode, final String authToken, final boolean isWhite) {
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(getAuthentication(authToken, currentRoleCode, isWhite));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用山分的认证中心接口,获取该token的绑定信息
|
||||||
|
*
|
||||||
|
* @param token
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Authentication getAuthentication(final String token, final String currentRoleCode,
|
||||||
|
final boolean isWhite) {
|
||||||
|
BaseCacheUser userInfo = client.getUserInfo(token);
|
||||||
|
// BaseCacheUser userInfo = ebtpClient.get();
|
||||||
|
log.debug("getUserInfo:{}", userInfo.toString());
|
||||||
|
// 对象为空, 则说明网络异常feign已熔断
|
||||||
|
if (Objects.isNull(userInfo)) {
|
||||||
|
if (!isWhite) {
|
||||||
|
throw new RemoteTimeoutException(REMOTE_ACCESS_FAILURE);
|
||||||
|
} else {
|
||||||
|
return new UsernamePasswordAuthenticationToken(new SecurityUser(), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ("temporaryUser".equals(userInfo.getUserId())) {
|
||||||
|
return new UsernamePasswordAuthenticationToken(new SecurityUser(), null, null);
|
||||||
|
}
|
||||||
|
SecurityUser securityUser = BeanUtil.toBean(userInfo, SecurityUser.class);
|
||||||
|
// 根据当前角色设定权限列表
|
||||||
|
List<RoleCodeAuthority> authorities = Optional.ofNullable(securityUser.getAuthorityList()).map(list -> {
|
||||||
|
return list.stream().filter(auth -> StringUtils.equals(auth.getRoleCode(), currentRoleCode))
|
||||||
|
.map(auth -> new RoleCodeAuthority(auth.getRoleCode())).collect(Collectors.toList());
|
||||||
|
}).orElse(Collections.emptyList());
|
||||||
|
|
||||||
|
return new UsernamePasswordAuthenticationToken(securityUser.setCurrentRoleCode(currentRoleCode), token,
|
||||||
|
authorities);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未发现token和session信息,则使用空的用户认证对象放行服务
|
||||||
|
*/
|
||||||
|
private void isNullThenAssignDefault() {
|
||||||
|
if (Objects.isNull(SecurityContextHolder.getContext().getAuthentication())) {
|
||||||
|
SecurityContextHolder.getContext()
|
||||||
|
.setAuthentication(new UsernamePasswordAuthenticationToken(new SecurityUser(), null, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
*
|
*
|
||||||
* @author Ajaxfan
|
* @author Ajaxfan
|
||||||
*/
|
*/
|
||||||
@FeignClient(value = "core-service-ebtp-userinfo")
|
@FeignClient(value = "sys-manager-ebtp-project")
|
||||||
public interface EbtpUserInfoClient {
|
public interface EbtpUserInfoClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,14 +12,14 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
*
|
*
|
||||||
* @author Ajaxfan
|
* @author Ajaxfan
|
||||||
*/
|
*/
|
||||||
@FeignClient(value = "${user.auth.resource.serviceId:mall-auth}",
|
@FeignClient(value = "${user.auth.resource.serviceId:sys-manager-ebtp-project}",
|
||||||
fallbackFactory = UnifastOAuthClientFallbackFactory.class)
|
fallbackFactory = UnifastOAuthClientFallbackFactory.class)
|
||||||
public interface UnifastOAuthClient {
|
public interface UnifastOAuthClient {
|
||||||
|
|
||||||
@GetMapping("oauth/check_token")
|
@GetMapping("/v1/userinfo/oauth/check_token")
|
||||||
SecurityEntity get(@RequestParam("token") String token);
|
SecurityEntity get(@RequestParam("token") String token);
|
||||||
|
|
||||||
@PostMapping("oauth/check_token")
|
@PostMapping("/v1/userinfo/oauth/check_token")
|
||||||
SecurityEntity getPost(@RequestParam("token") String token);
|
SecurityEntity getPost(@RequestParam("token") String token);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,35 @@
|
|||||||
|
|
||||||
package com.chinaunicom.mall.ebtp.cloud.userinfo.starter.service.impl;
|
package com.chinaunicom.mall.ebtp.cloud.userinfo.starter.service.impl;
|
||||||
|
|
||||||
|
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.HEADER_CHECK_TOKEN;
|
||||||
|
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.REDIS_USER_KEY;
|
||||||
|
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_PREFIX;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.remoting.RemoteTimeoutException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.AuthorityEntity;
|
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.security.starter.entity.SecurityEntity;
|
||||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.client.EbtpUserInfoClient;
|
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.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.entity.CheckTokenVo;
|
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.entity.CheckTokenVo;
|
||||||
import com.chinaunicom.mall.ebtp.cloud.userinfo.starter.service.UserInfoService;
|
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.base.entity.BaseCacheUser;
|
||||||
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
|
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
|
||||||
import com.chinaunicom.mall.ebtp.common.util.JsonUtils;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.*;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -33,8 +38,9 @@ public class UserInfoServiceImpl implements UserInfoService {
|
|||||||
private @Autowired
|
private @Autowired
|
||||||
UnifastOAuthClient client;
|
UnifastOAuthClient client;
|
||||||
// private @Autowired ObjectMapper userInfoObjectMapper;
|
// private @Autowired ObjectMapper userInfoObjectMapper;
|
||||||
|
@Value("${login.token.time_limit:3}")
|
||||||
@Autowired(required = false)
|
private Integer valid_time_limit;
|
||||||
|
@Autowired()
|
||||||
@Qualifier("userinfoRedisTemplate")
|
@Qualifier("userinfoRedisTemplate")
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@ -59,7 +65,7 @@ public class UserInfoServiceImpl implements UserInfoService {
|
|||||||
|
|
||||||
BaseCacheUser user = structureUser(token);
|
BaseCacheUser user = structureUser(token);
|
||||||
|
|
||||||
redisTemplate.opsForValue().set(REDIS_USER_KEY + token, user, 5, TimeUnit.MINUTES);
|
redisTemplate.opsForValue().set(REDIS_USER_KEY + token, user, valid_time_limit-1, TimeUnit.MINUTES);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
@ -72,44 +78,44 @@ public class UserInfoServiceImpl implements UserInfoService {
|
|||||||
BaseCacheUser user = convertToBusinessModel(getAuthentication(token));
|
BaseCacheUser user = convertToBusinessModel(getAuthentication(token));
|
||||||
|
|
||||||
//获取redis中extend的缓存
|
//获取redis中extend的缓存
|
||||||
Object extendRedis = redisTemplate.opsForValue().get(REDIS_USER_KEY_EXTEND);
|
// Object extendRedis = redisTemplate.opsForValue().get(REDIS_USER_KEY_EXTEND);
|
||||||
if (extendRedis == null) {
|
// if (extendRedis == null) {
|
||||||
//查extend库 刷新缓存
|
// //查extend库 刷新缓存
|
||||||
ResponseEntity<Boolean> response = ebtpClient.refreshToken();
|
// ResponseEntity<Boolean> response = ebtpClient.refreshToken();
|
||||||
if (response.getStatusCode().value() != 200 || Boolean.FALSE.equals(response.getBody())) {
|
// if (response.getStatusCode().value() != 200 || Boolean.FALSE.equals(response.getBody())) {
|
||||||
log.info("获取extend服务的user缓存失败");
|
// log.info("获取extend服务的user缓存失败");
|
||||||
}
|
// }
|
||||||
extendRedis = redisTemplate.opsForValue().get(REDIS_USER_KEY_EXTEND);
|
// extendRedis = redisTemplate.opsForValue().get(REDIS_USER_KEY_EXTEND);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// if (extendRedis == null) {
|
||||||
|
// return user;
|
||||||
|
// }
|
||||||
|
|
||||||
if (extendRedis == null) {
|
// Map<String, String> userTable = JsonUtils.jsonToPojo(String.valueOf(extendRedis), Map.class);
|
||||||
return user;
|
// //获取用户信息
|
||||||
}
|
// List<CacheUser> users = JsonUtils.jsonToList(userTable.get(USERS), CacheUser.class);
|
||||||
|
// CacheUser baseUser = users.stream().filter(u -> u.getAccount().equals(user.getLoginName())).findFirst().orElse(null);
|
||||||
Map<String, String> userTable = JsonUtils.jsonToPojo(String.valueOf(extendRedis), Map.class);
|
// if (Objects.isNull(baseUser)) {
|
||||||
//获取用户信息
|
// return user;
|
||||||
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)) {
|
// List<CacheRole> roles = JsonUtils.jsonToList(userTable.get(ROLES), CacheRole.class);
|
||||||
return user;
|
// // user.setProvince(baseUser.getProvince())
|
||||||
}
|
// //覆盖角色
|
||||||
|
// user.setAuthorityList(
|
||||||
List<CacheRole> roles = JsonUtils.jsonToList(userTable.get(ROLES), CacheRole.class);
|
// Optional.of(roles
|
||||||
user.setProvince(baseUser.getProvince())
|
// .stream()
|
||||||
//覆盖角色
|
// .filter(r -> baseUser.getRole().contains(r.getRole()))
|
||||||
.setAuthorityList(
|
// .map(br ->
|
||||||
Optional.of(roles
|
// new AuthorityEntity()
|
||||||
.stream()
|
// .setRoleId(br.getRoleId())
|
||||||
.filter(r -> baseUser.getRole().contains(r.getRole()))
|
// .setRoleCode(br.getRole())
|
||||||
.map(br ->
|
// .setRoleName(br.getRemarks())
|
||||||
new AuthorityEntity()
|
// .setRoleScope("EBTP")
|
||||||
.setRoleId(br.getRoleId())
|
// .setAuthorities(Collections.emptyList()))
|
||||||
.setRoleCode(br.getRole())
|
// .collect(Collectors.toList()))
|
||||||
.setRoleName(br.getRemarks())
|
// .orElseGet(Collections::emptyList));
|
||||||
.setRoleScope("EBTP")
|
|
||||||
.setAuthorities(Collections.emptyList()))
|
|
||||||
.collect(Collectors.toList()))
|
|
||||||
.orElseGet(Collections::emptyList));
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,12 +143,12 @@ public class UserInfoServiceImpl implements UserInfoService {
|
|||||||
|
|
||||||
adapterUserSource(user, raw);
|
adapterUserSource(user, raw);
|
||||||
|
|
||||||
replenishAuthority(user);
|
// replenishAuthority(user);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 为联通用户添加默认角色
|
* 为中远用户添加默认角色
|
||||||
*
|
*
|
||||||
* @param user
|
* @param user
|
||||||
*/
|
*/
|
||||||
@ -151,8 +157,8 @@ public class UserInfoServiceImpl implements UserInfoService {
|
|||||||
|
|
||||||
if (authorityList.isEmpty() && "0".equals(user.getUserType())) {
|
if (authorityList.isEmpty() && "0".equals(user.getUserType())) {
|
||||||
authorityList.add(new AuthorityEntity()
|
authorityList.add(new AuthorityEntity()
|
||||||
.setRoleId("20004").setRoleCode("ebtp-unicom-default")
|
.setRoleId("20004").setRoleCode("ebtp-cosco-default")
|
||||||
.setRoleName("联通普通用户").setRoleScope("EBTP"));
|
.setRoleName("中远普通用户").setRoleScope("EBTP"));
|
||||||
user.setAuthorityList(authorityList);
|
user.setAuthorityList(authorityList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,7 +169,7 @@ public class UserInfoServiceImpl implements UserInfoService {
|
|||||||
* @param raw
|
* @param raw
|
||||||
*/
|
*/
|
||||||
private void adapterUserSource(BaseCacheUser user, SecurityEntity raw) {
|
private void adapterUserSource(BaseCacheUser user, SecurityEntity raw) {
|
||||||
if ("0".equals(raw.getUserSource())) {// 联通用户
|
if ("0".equals(raw.getUserSource())) {// 中远用户
|
||||||
user.setOrganizationId(raw.getOrgId()).setOrganizationName(raw.getOrgName()).setDeptId(raw.getOu())
|
user.setOrganizationId(raw.getOrgId()).setOrganizationName(raw.getOrgName()).setDeptId(raw.getOu())
|
||||||
.setDeptName(raw.getOuName());
|
.setDeptName(raw.getOuName());
|
||||||
} else {
|
} else {
|
||||||
|
@ -3,7 +3,14 @@ package com.chinaunicom.mall.ebtp.common.base.service.impl;
|
|||||||
import com.chinaunicom.mall.ebtp.common.base.entity.BaseCacheUser;
|
import com.chinaunicom.mall.ebtp.common.base.entity.BaseCacheUser;
|
||||||
import com.chinaunicom.mall.ebtp.common.base.service.IBaseCacheUserService;
|
import com.chinaunicom.mall.ebtp.common.base.service.IBaseCacheUserService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import com.chinaunicom.mall.ebtp.cloud.security.starter.filter.BearerTokenHolder;
|
||||||
|
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.REDIS_USER_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存用户service实现层 获取缓存用户信息
|
* 缓存用户service实现层 获取缓存用户信息
|
||||||
@ -16,18 +23,29 @@ import org.springframework.stereotype.Service;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class BaseCacheUserServiceImpl implements IBaseCacheUserService {
|
public class BaseCacheUserServiceImpl implements IBaseCacheUserService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("userinfoRedisTemplate")
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseCacheUser getCacheUser() {
|
public BaseCacheUser getCacheUser() {
|
||||||
BaseCacheUser buser = new BaseCacheUser();
|
|
||||||
try {
|
try {
|
||||||
// BeanUtils.copyProperties(SecurityContextHolder.getContext().getAuthentication().getPrincipal(), buser);
|
String token = BearerTokenHolder.getToken();
|
||||||
|
if (token == null || token.isEmpty()) {
|
||||||
|
log.warn("未获取到token");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Object o = redisTemplate.opsForValue().get(REDIS_USER_KEY + token);
|
||||||
|
if (o instanceof BaseCacheUser) {
|
||||||
|
return (BaseCacheUser) o;
|
||||||
|
} else {
|
||||||
|
log.warn("redis中未找到用户信息,token:{}", token);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage());
|
log.error("获取缓存用户信息异常", e);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
log.debug("Current user principal: " + buser);
|
|
||||||
|
|
||||||
return buser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ spring:
|
|||||||
password: Unicom#135
|
password: Unicom#135
|
||||||
|
|
||||||
# 天宫Eureka配置
|
# 天宫Eureka配置
|
||||||
eureka:asdf
|
eureka:
|
||||||
client:
|
client:
|
||||||
service-url:
|
service-url:
|
||||||
defaultZone: http://10.242.37.148:5001/eureka
|
defaultZone: http://10.242.37.148:5001/eureka
|
||||||
|
Reference in New Issue
Block a user