From 9ca2d061c79ba6a8a747363c2a5b0f490b269efb Mon Sep 17 00:00:00 2001 From: houjishuang <46269784@qq.com> Date: Thu, 19 Jun 2025 11:28:12 +0800 Subject: [PATCH 1/3] jiaoyan --- uboot-common/pom.xml | 6 + .../starter/entity/RoleCodeAuthority.java | 23 ++ .../filter/TokenAuthenticationFilter.java | 325 ++++++++++++++++++ .../starter/client/EbtpUserInfoClient.java | 2 +- .../starter/client/UnifastOAuthClient.java | 6 +- .../service/impl/UserInfoServiceImpl.java | 92 ++--- .../impl/BaseCacheUserServiceImpl.java | 4 +- 7 files changed, 408 insertions(+), 50 deletions(-) create mode 100644 uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/RoleCodeAuthority.java create mode 100644 uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java diff --git a/uboot-common/pom.xml b/uboot-common/pom.xml index 876007d..ad87de6 100644 --- a/uboot-common/pom.xml +++ b/uboot-common/pom.xml @@ -16,6 +16,12 @@ uboot-common + + org.springframework.security + spring-security-core + 5.7.3 + + diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/RoleCodeAuthority.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/RoleCodeAuthority.java new file mode 100644 index 0000000..8866251 --- /dev/null +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/RoleCodeAuthority.java @@ -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; + } + +} diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java new file mode 100644 index 0000000..33cb657 --- /dev/null +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java @@ -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 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 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, 20, TimeUnit.SECONDS); + } + }else{ + redisTemplate.opsForValue().set(HEADER_CHECK_TOKEN+":"+cookieKey, 1, 20, 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 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)); + } + } + + +} diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/client/EbtpUserInfoClient.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/client/EbtpUserInfoClient.java index db99498..49b4af6 100644 --- a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/client/EbtpUserInfoClient.java +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/client/EbtpUserInfoClient.java @@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.RequestParam; * * @author Ajaxfan */ -@FeignClient(value = "core-service-ebtp-userinfo") +@FeignClient(value = "sys-manager-ebtp-project") public interface EbtpUserInfoClient { /** diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/client/UnifastOAuthClient.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/client/UnifastOAuthClient.java index db5ca5a..42d5007 100644 --- a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/client/UnifastOAuthClient.java +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/client/UnifastOAuthClient.java @@ -12,14 +12,14 @@ import org.springframework.web.bind.annotation.RequestParam; * * @author Ajaxfan */ -@FeignClient(value = "${user.auth.resource.serviceId:mall-auth}", +@FeignClient(value = "${user.auth.resource.serviceId:sys-manager-ebtp-project}", fallbackFactory = UnifastOAuthClientFallbackFactory.class) public interface UnifastOAuthClient { - @GetMapping("oauth/check_token") + @GetMapping("/v1/userinfo/oauth/check_token") SecurityEntity get(@RequestParam("token") String token); - @PostMapping("oauth/check_token") + @PostMapping("/v1/userinfo/oauth/check_token") SecurityEntity getPost(@RequestParam("token") String token); } diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java index e204617..7b85b62 100644 --- a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java @@ -15,6 +15,7 @@ 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.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.ResponseEntity; import org.springframework.remoting.RemoteTimeoutException; @@ -33,8 +34,9 @@ public class UserInfoServiceImpl implements UserInfoService { private @Autowired UnifastOAuthClient client; // private @Autowired ObjectMapper userInfoObjectMapper; - - @Autowired(required = false) +@Value("${login.token.time_limit}") +private Integer valid_time_limit; + @Autowired() @Qualifier("userinfoRedisTemplate") private RedisTemplate redisTemplate; @@ -59,7 +61,7 @@ public class UserInfoServiceImpl implements UserInfoService { 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, TimeUnit.MINUTES); return user; } @@ -72,44 +74,44 @@ public class UserInfoServiceImpl implements UserInfoService { BaseCacheUser user = convertToBusinessModel(getAuthentication(token)); //获取redis中extend的缓存 - Object extendRedis = redisTemplate.opsForValue().get(REDIS_USER_KEY_EXTEND); - if (extendRedis == null) { - //查extend库 刷新缓存 - ResponseEntity 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); - } +// Object extendRedis = redisTemplate.opsForValue().get(REDIS_USER_KEY_EXTEND); +// if (extendRedis == null) { +// //查extend库 刷新缓存 +// ResponseEntity 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; +// } - if (extendRedis == null) { - return user; - } - - Map userTable = JsonUtils.jsonToPojo(String.valueOf(extendRedis), Map.class); - //获取用户信息 - List 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 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)); +// Map userTable = JsonUtils.jsonToPojo(String.valueOf(extendRedis), Map.class); +// //获取用户信息 +// List 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 roles = JsonUtils.jsonToList(userTable.get(ROLES), CacheRole.class); +// // user.setProvince(baseUser.getProvince()) +// //覆盖角色 +// user.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; } @@ -137,12 +139,12 @@ public class UserInfoServiceImpl implements UserInfoService { adapterUserSource(user, raw); - replenishAuthority(user); + // replenishAuthority(user); return user; } /** - * 为联通用户添加默认角色 + * 为中远用户添加默认角色 * * @param user */ @@ -151,8 +153,8 @@ public class UserInfoServiceImpl implements UserInfoService { if (authorityList.isEmpty() && "0".equals(user.getUserType())) { authorityList.add(new AuthorityEntity() - .setRoleId("20004").setRoleCode("ebtp-unicom-default") - .setRoleName("联通普通用户").setRoleScope("EBTP")); + .setRoleId("20004").setRoleCode("ebtp-cosco-default") + .setRoleName("中远普通用户").setRoleScope("EBTP")); user.setAuthorityList(authorityList); } } @@ -163,7 +165,7 @@ public class UserInfoServiceImpl implements UserInfoService { * @param 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()) .setDeptName(raw.getOuName()); } else { diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/common/base/service/impl/BaseCacheUserServiceImpl.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/common/base/service/impl/BaseCacheUserServiceImpl.java index 55c365d..7d0ef14 100644 --- a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/common/base/service/impl/BaseCacheUserServiceImpl.java +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/common/base/service/impl/BaseCacheUserServiceImpl.java @@ -3,6 +3,8 @@ 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.service.IBaseCacheUserService; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; /** @@ -21,7 +23,7 @@ public class BaseCacheUserServiceImpl implements IBaseCacheUserService { public BaseCacheUser getCacheUser() { BaseCacheUser buser = new BaseCacheUser(); try { -// BeanUtils.copyProperties(SecurityContextHolder.getContext().getAuthentication().getPrincipal(), buser); + BeanUtils.copyProperties(SecurityContextHolder.getContext().getAuthentication().getPrincipal(), buser); } catch (Exception e) { log.error(e.getMessage()); } From 46b3ca6e718273a0ce70f00625a89d9c6c811bc9 Mon Sep 17 00:00:00 2001 From: houjishuang <46269784@qq.com> Date: Fri, 20 Jun 2025 16:56:49 +0800 Subject: [PATCH 2/3] =?UTF-8?q?jiaoyan=E6=94=B9=E4=B8=BA5=E7=A7=92?= =?UTF-8?q?=E5=86=85=E4=B8=8D=E5=8F=AF=E9=87=8D=E5=A4=8D=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/starter/filter/TokenAuthenticationFilter.java | 4 ++-- .../userinfo/starter/service/impl/UserInfoServiceImpl.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java index 33cb657..1230702 100644 --- a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java @@ -190,10 +190,10 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter { log.error("请求连接已使用过"); b = false; }else{ - redisTemplate.opsForValue().set(HEADER_CHECK_TOKEN+":"+cookieKey, 2, 20, TimeUnit.SECONDS); + redisTemplate.opsForValue().set(HEADER_CHECK_TOKEN+":"+cookieKey, 2, 5, TimeUnit.SECONDS); } }else{ - redisTemplate.opsForValue().set(HEADER_CHECK_TOKEN+":"+cookieKey, 1, 20, TimeUnit.SECONDS); + redisTemplate.opsForValue().set(HEADER_CHECK_TOKEN+":"+cookieKey, 1, 5, TimeUnit.SECONDS); } String header = request.getHeader(AUTHORIZATION_HEADER);//请求头token diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java index 7b85b62..43fd794 100644 --- a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java @@ -34,7 +34,7 @@ public class UserInfoServiceImpl implements UserInfoService { private @Autowired UnifastOAuthClient client; // private @Autowired ObjectMapper userInfoObjectMapper; -@Value("${login.token.time_limit}") +@Value("${login.token.time_limit:3}") private Integer valid_time_limit; @Autowired() @Qualifier("userinfoRedisTemplate") @@ -61,7 +61,7 @@ private Integer valid_time_limit; BaseCacheUser user = structureUser(token); - redisTemplate.opsForValue().set(REDIS_USER_KEY + token, user, valid_time_limit, TimeUnit.MINUTES); + redisTemplate.opsForValue().set(REDIS_USER_KEY + token, user, valid_time_limit-1, TimeUnit.MINUTES); return user; } From f37496a35162b1a5dc6e1991914a5cfe2d7c292b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=80=A1?= Date: Thu, 10 Jul 2025 10:10:46 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uboot-common/pom.xml | 2 +- .../starter/filter/BearerTokenFilter.java | 31 ++++++++++++++++ .../filter/BearerTokenFilterConfig.java | 18 ++++++++++ .../starter/filter/BearerTokenHolder.java | 17 +++++++++ .../service/impl/UserInfoServiceImpl.java | 36 ++++++++++--------- .../impl/BaseCacheUserServiceImpl.java | 28 +++++++++++---- .../src/main/resources/application-common.yml | 4 +-- 7 files changed, 111 insertions(+), 25 deletions(-) create mode 100644 uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenFilter.java create mode 100644 uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenFilterConfig.java create mode 100644 uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenHolder.java diff --git a/uboot-common/pom.xml b/uboot-common/pom.xml index ad87de6..aeb3de6 100644 --- a/uboot-common/pom.xml +++ b/uboot-common/pom.xml @@ -122,7 +122,7 @@ poi-ooxml-schemas - + diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenFilter.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenFilter.java new file mode 100644 index 0000000..f6f74e0 --- /dev/null +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenFilter.java @@ -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(); + } + } +} \ No newline at end of file diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenFilterConfig.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenFilterConfig.java new file mode 100644 index 0000000..94dca89 --- /dev/null +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenFilterConfig.java @@ -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 bearerTokenFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(new BearerTokenFilter()); + registration.addUrlPatterns("/*"); + registration.setName("bearerTokenFilter"); + registration.setOrder(-100); // 优先级高于 Spring Security + return registration; + } +} \ No newline at end of file diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenHolder.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenHolder.java new file mode 100644 index 0000000..4f36ada --- /dev/null +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/BearerTokenHolder.java @@ -0,0 +1,17 @@ +package com.chinaunicom.mall.ebtp.cloud.security.starter.filter; + +public class BearerTokenHolder { + private static final ThreadLocal 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(); + } +} \ No newline at end of file diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java index 43fd794..3a99a48 100644 --- a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/cloud/userinfo/starter/service/impl/UserInfoServiceImpl.java @@ -1,31 +1,35 @@ 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.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.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.base.entity.BaseResponse; -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.beans.factory.annotation.Value; -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 @Service diff --git a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/common/base/service/impl/BaseCacheUserServiceImpl.java b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/common/base/service/impl/BaseCacheUserServiceImpl.java index 7d0ef14..4c50b6a 100644 --- a/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/common/base/service/impl/BaseCacheUserServiceImpl.java +++ b/uboot-common/src/main/java/com/chinaunicom/mall/ebtp/common/base/service/impl/BaseCacheUserServiceImpl.java @@ -4,8 +4,13 @@ import com.chinaunicom.mall.ebtp.common.base.entity.BaseCacheUser; import com.chinaunicom.mall.ebtp.common.base.service.IBaseCacheUserService; 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 com.chinaunicom.mall.ebtp.cloud.security.starter.filter.BearerTokenHolder; +import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.REDIS_USER_KEY; /** * 缓存用户service实现层 获取缓存用户信息 @@ -18,18 +23,29 @@ import org.springframework.stereotype.Service; @Slf4j public class BaseCacheUserServiceImpl implements IBaseCacheUserService { + @Autowired + @Qualifier("userinfoRedisTemplate") + private RedisTemplate redisTemplate; @Override public BaseCacheUser getCacheUser() { - BaseCacheUser buser = new BaseCacheUser(); 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) { - log.error(e.getMessage()); + log.error("获取缓存用户信息异常", e); + return null; } - log.debug("Current user principal: " + buser); - - return buser; } } diff --git a/uboot-common/src/main/resources/application-common.yml b/uboot-common/src/main/resources/application-common.yml index 36cab29..fa6c82a 100644 --- a/uboot-common/src/main/resources/application-common.yml +++ b/uboot-common/src/main/resources/application-common.yml @@ -83,7 +83,7 @@ spring: password: Unicom#135 # 天宫Eureka配置 -eureka:asdf +eureka: client: service-url: defaultZone: http://10.242.37.148:5001/eureka @@ -154,4 +154,4 @@ management: http: rsa: publicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNR+qWwx1SFELNYCk3vqqQ9wAgr7il6/yRPnwk/Vq+7UAlUyOrlTb9ZAKAxJE7OjoqQHpPJkXYypqlNkkpYrRHKc3lTeSXFL1AOU6idtidTC1W7STwNNYJ1RtFA7qqVd4C/+pbU0GHZ2OMsMbFr+b40pienLBg0FGGGCoRVbOSxwIDAQAB - privateKey: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM1H6pbDHVIUQs1gKTe+qpD3ACCvuKXr/JE+fCT9Wr7tQCVTI6uVNv1kAoDEkTs6OipAek8mRdjKmqU2SSlitEcpzeVN5JcUvUA5TqJ22J1MLVbtJPA01gnVG0UDuqpV3gL/6ltTQYdnY4ywxsWv5vjSmJ6csGDQUYYYKhFVs5LHAgMBAAECgYBJsk/d4B5eoTd6U9N4V9MUSBibo3o+1wHNgwk+nlY9xR8KR1a++srLHWRopikdgkHveUZvs+XPdq0eMucBHJZrcVT9ZT4ehPmCyRZzILjKqZugP5MpTj1CtM5SfQtxsfuJmM5LYvVX2lmYQw2k+MyWNfyrVfH6HVvu19l1sBqpAQJBAOW2LlqTACRPD3+IOFrHlRQvuUrLq38eRFZCRte2UEq0fMv8VKlgwZdMynD40LwAeO0Cz9huQkNFx4WGxOXthnECQQDkxf43WY6MltfTATYQy4h/TKHznKG+9dMNVFf3SkNECGh5IcW21v44s5X6zOl6zbPVtiySq/c2t9/IbbSc2/i3AkAa3q6ZZayUkrLrZhHBfKsRi2uPNje/TNkNhf8naGoH8wjOC5wTm//JJPBhOpmgBCYhAz0wweT6XYUzN0p84sXhAkEAh7ak7nTkSaaadgQ77I6xdMMjN/9tPHlcMIYegQa/DLboMyPDxImZ2k0+5b91qnIpAtjFbGUzjHRb/uyFvqAH1QJBAJsS6/GhMoCDyPdGQAMA+KylB1s6o8sowLx92q6oBs03idtvFxAocIej1m1UuCW+EpT+ZoFwOn+sdCm5VKfVoLQ= \ No newline at end of file + privateKey: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAM1H6pbDHVIUQs1gKTe+qpD3ACCvuKXr/JE+fCT9Wr7tQCVTI6uVNv1kAoDEkTs6OipAek8mRdjKmqU2SSlitEcpzeVN5JcUvUA5TqJ22J1MLVbtJPA01gnVG0UDuqpV3gL/6ltTQYdnY4ywxsWv5vjSmJ6csGDQUYYYKhFVs5LHAgMBAAECgYBJsk/d4B5eoTd6U9N4V9MUSBibo3o+1wHNgwk+nlY9xR8KR1a++srLHWRopikdgkHveUZvs+XPdq0eMucBHJZrcVT9ZT4ehPmCyRZzILjKqZugP5MpTj1CtM5SfQtxsfuJmM5LYvVX2lmYQw2k+MyWNfyrVfH6HVvu19l1sBqpAQJBAOW2LlqTACRPD3+IOFrHlRQvuUrLq38eRFZCRte2UEq0fMv8VKlgwZdMynD40LwAeO0Cz9huQkNFx4WGxOXthnECQQDkxf43WY6MltfTATYQy4h/TKHznKG+9dMNVFf3SkNECGh5IcW21v44s5X6zOl6zbPVtiySq/c2t9/IbbSc2/i3AkAa3q6ZZayUkrLrZhHBfKsRi2uPNje/TNkNhf8naGoH8wjOC5wTm//JJPBhOpmgBCYhAz0wweT6XYUzN0p84sXhAkEAh7ak7nTkSaaadgQ77I6xdMMjN/9tPHlcMIYegQa/DLboMyPDxImZ2k0+5b91qnIpAtjFbGUzjHRb/uyFvqAH1QJBAJsS6/GhMoCDyPdGQAMA+KylB1s6o8sowLx92q6oBs03idtvFxAocIej1m1UuCW+EpT+ZoFwOn+sdCm5VKfVoLQ=