修改代码,去除apollo、security和seata配置,替换为nacos
This commit is contained in:
@ -45,11 +45,11 @@
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--seata-->
|
||||
<dependency>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- <!–seata–>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>io.seata</groupId>-->
|
||||
<!-- <artifactId>seata-spring-boot-starter</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
6
pom.xml
6
pom.xml
@ -211,6 +211,12 @@
|
||||
<version>${redisson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<version>${com.alibaba.cloud.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
@ -51,17 +51,14 @@
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--apollo-->
|
||||
<dependency>
|
||||
<groupId>com.ctrip.framework.apollo</groupId>
|
||||
<artifactId>apollo-client</artifactId>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--eureka-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--feign-->
|
||||
@ -120,10 +117,10 @@
|
||||
</dependency>
|
||||
|
||||
<!--security-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-security</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.springframework.cloud</groupId>-->
|
||||
<!-- <artifactId>spring-cloud-security</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!--swagger-->
|
||||
<dependency>
|
||||
|
@ -1,55 +0,0 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.apollo.starter;
|
||||
|
||||
|
||||
import com.ctrip.framework.apollo.model.ConfigChange;
|
||||
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
|
||||
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author f
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@Configuration
|
||||
public class ApolloHotLoading implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
@Value("${spring.application.name}")
|
||||
private String applicationName;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
|
||||
@ApolloConfigChangeListener()
|
||||
private void someChangeHandler(ConfigChangeEvent changeEvent) {
|
||||
log.info(" ------------------- {} apolloHotLoading start ------------------", applicationName);
|
||||
|
||||
for (String changedKey : changeEvent.changedKeys()) {
|
||||
|
||||
ConfigChange configChange = changeEvent.getChange(changedKey);
|
||||
String oldValue = configChange.getOldValue();
|
||||
String newValue = configChange.getNewValue();
|
||||
log.info("changedKey:【{}】,oldValue=【{}】, newValue:【{}】", changedKey, oldValue, newValue);
|
||||
}
|
||||
|
||||
refreshProperties(changeEvent);
|
||||
|
||||
log.info(" ------------------- {} apolloHotLoading end ------------------", applicationName);
|
||||
}
|
||||
|
||||
public void refreshProperties(ConfigChangeEvent changeEvent) {
|
||||
// 更新相应的bean的属性值,主要是存在@ConfigurationProperties注解的bean
|
||||
this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.apollo.starter;
|
||||
|
||||
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
/**
|
||||
* apollo自动装配
|
||||
*
|
||||
* @author ajaxfan
|
||||
*/
|
||||
@EnableApolloConfig
|
||||
@Configuration
|
||||
@PropertySource("classpath:configuration/apollo-configuration.properties")
|
||||
public class ApolloStarterConfiguration {
|
||||
|
||||
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.eureka.starter;
|
||||
|
||||
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
/**
|
||||
* eureka 自动装配
|
||||
*
|
||||
* @author ajaxfan
|
||||
*/
|
||||
@Configuration
|
||||
@PropertySource("classpath:configuration/eureka-cofiguration.properties")
|
||||
public class EurekaStarterConfiguration {
|
||||
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.security.starter;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.InsufficientAuthenticationException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.*;
|
||||
|
||||
/**
|
||||
* 通过实现EntryPoint接口,自定义spring security异常返回
|
||||
*
|
||||
* @author Administrator
|
||||
*/
|
||||
@Slf4j
|
||||
public class UserAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
private static final String RESPONSE_CONTENT_TYPE = "application/json;charset=utf-8";
|
||||
private static final String DEFAULT_ERROR_MESSAGE = "System Generic Error";
|
||||
|
||||
/**
|
||||
* @param request
|
||||
* @param response
|
||||
* @param authException
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException, ServletException {
|
||||
response.setContentType(RESPONSE_CONTENT_TYPE);
|
||||
|
||||
String code = (String) request.getSession().getAttribute("code");// security filter 返回的自定义状态码
|
||||
log.info("commence :"+code);
|
||||
//未获取到token 且不在白名单
|
||||
if (authException instanceof InsufficientAuthenticationException) {
|
||||
code = REMOTE_ACCESS_FAILURE;
|
||||
}
|
||||
Map<String, Object> map = adapterException(StringUtils.defaultIfBlank(code, DEFAULT_ERROR_MESSAGE), response);
|
||||
map.put("success", false);
|
||||
map.put("path", request.getServletPath());
|
||||
map.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
||||
|
||||
try {
|
||||
new ObjectMapper().writeValue(response.getOutputStream(), map);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code
|
||||
*/
|
||||
private Map<String, Object> adapterException(String code, HttpServletResponse response) {
|
||||
switch (code) {
|
||||
case TOKEN_EXPIRED:
|
||||
return accessDenidedException(code, response);
|
||||
case REMOTE_ACCESS_FAILURE:
|
||||
return remoteTimeoutException(code, response);
|
||||
case REMOTE_ACCESS_CHECK:
|
||||
return remoteCheckException(code, response);
|
||||
default:
|
||||
return globalException(code, response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* token 已失效
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Object> accessDenidedException(String code, HttpServletResponse response) {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("code", code);
|
||||
map.put("message", "登录已超期");
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token 远程认证服务超时
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Object> remoteTimeoutException(String code, HttpServletResponse response) {
|
||||
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("code", code);
|
||||
map.put("message", "网络繁忙,请稍后再试");
|
||||
|
||||
return map;
|
||||
}
|
||||
/**
|
||||
* Token 远程认证服务超时
|
||||
*
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Object> remoteCheckException(String code, HttpServletResponse response) {
|
||||
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("code", code);
|
||||
map.put("message", "无效请求");
|
||||
|
||||
return map;
|
||||
}
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private Map<String, Object> globalException(String code, HttpServletResponse response) {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("code", -1);
|
||||
map.put("message", code);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package com.chinaunicom.mall.ebtp.cloud.security.starter.config;
|
||||
|
||||
import com.chinaunicom.mall.ebtp.cloud.security.starter.UserAuthenticationEntryPoint;
|
||||
import com.chinaunicom.mall.ebtp.cloud.security.starter.filter.TokenAuthenticationFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* 安全设置
|
||||
*
|
||||
* @author Ajaxfan
|
||||
*/
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = false, jsr250Enabled = true, securedEnabled = true)
|
||||
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
public TokenAuthenticationFilter authenticationTokenFilterBean() {
|
||||
return new TokenAuthenticationFilter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationEntryPoint authenticationEntryPoint() {
|
||||
return new UserAuthenticationEntryPoint();
|
||||
}
|
||||
|
||||
/**
|
||||
* 向Filter链中插入自定义TokenFilter
|
||||
*
|
||||
* @param http
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint()).and().sessionManagement()
|
||||
// Spring security 默认是使用 HttpSessionSecurityContextRepository 来存储SecurityContext
|
||||
// 的, 因我们的应用系统不是基于 login 认证模式, 如果开启session 则会产生 token 缓存问题(即新的请求可能使用的是过期token)
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
|
||||
// 只对业务节点请求做认证处理
|
||||
// .authorizeRequests().antMatchers("/v1/**").authenticated().and()
|
||||
.authorizeRequests().anyRequest().authenticated().and()
|
||||
.httpBasic().and().csrf().disable();
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -1,324 +0,0 @@
|
||||
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.base.entity.BaseResponse;
|
||||
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.beans.factory.annotation.Value;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
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.Cookie;
|
||||
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 java.util.stream.Stream;
|
||||
|
||||
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, 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, "");
|
||||
String cookieValue = "";
|
||||
try {
|
||||
cookieValue = RSAcheck.decrypt(cookieKey, checkTokenVo.getCheckprivateKey());//checkprivateKey
|
||||
}catch (Exception e){
|
||||
b = false;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -3,8 +3,6 @@ package com.chinaunicom.mall.ebtp.common;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
|
@ -3,14 +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;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 缓存用户service实现层 获取缓存用户信息
|
||||
*
|
||||
@ -27,7 +21,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());
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ import static com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants.
|
||||
/**
|
||||
* 通过拦截器来为header注入token
|
||||
*/
|
||||
@Configuration
|
||||
//@Configuration
|
||||
@Slf4j
|
||||
public class FeignConfig implements RequestInterceptor {
|
||||
|
||||
|
@ -12,12 +12,8 @@
|
||||
# security
|
||||
# swagger
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.chinaunicom.mall.ebtp.cloud.apollo.starter.ApolloStarterConfiguration,\
|
||||
com.chinaunicom.ebtp.mall.cloud.attachment.sdk.config.SDKAutoConfiguration,\
|
||||
com.chinaunicom.mall.ebtp.cloud.eureka.starter.EurekaStarterConfiguration,\
|
||||
com.chinaunicom.mall.ebtp.cloud.feign.starter.FeignStarterConfiguration,\
|
||||
com.chinaunicom.mall.ebtp.cloud.log.starter.LogStarterConfiguration,\
|
||||
com.chinaunicom.mall.ebtp.cloud.redis.starter.RedisStarterConfiguration,\
|
||||
com.chinaunicom.mall.ebtp.cloud.security.starter.SecurityStarterConfiguration,\
|
||||
com.chinaunicom.mall.ebtp.cloud.security.starter.config.BrowserSecurityConfig,\
|
||||
com.chinaunicom.mall.ebtp.cloud.swagger.starter.SwaggerStarterConfiguration
|
||||
com.chinaunicom.mall.ebtp.cloud.swagger.starter.SwaggerStarterConfiguration
|
||||
|
@ -3,8 +3,6 @@ package com.chinaunicom.mall.ebtp.core;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@MapperScan({"com.chinaunicom.mall.ebtp.core.**.dao"})
|
||||
|
@ -1,20 +0,0 @@
|
||||
package com.chinaunicom.mall.ebtp.core.config;
|
||||
|
||||
import com.chinaunicom.mall.ebtp.common.config.FeignConfig;
|
||||
import feign.RequestTemplate;
|
||||
import io.seata.core.context.RootContext;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class FeignSeataConfig extends FeignConfig {
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate template) {
|
||||
String xid = RootContext.getXID();
|
||||
if (StringUtils.isNotEmpty(xid)) {
|
||||
template.header(RootContext.KEY_XID, xid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package com.chinaunicom.mall.ebtp.core.config;
|
||||
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
|
||||
import io.seata.core.context.RootContext;
|
||||
import io.seata.core.exception.RmTransactionException;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 异常处理 拦截BindException异常,返回HttpStatus是400的绑定错误信息
|
||||
* 拦截FrameException异常,返回HttpStatus是406的业务处理错误信息(支持自定义状态码)
|
||||
* 拦截Exception异常,返回HttpStatus是500服务器内部异常
|
||||
*
|
||||
* @author fqj
|
||||
* @date 2020年9月3日 11:42:25
|
||||
*/
|
||||
@Slf4j
|
||||
@ControllerAdvice
|
||||
@Order(1)
|
||||
@ResponseBody
|
||||
@ConditionalOnProperty(name = "mconfig.io.seata.core.exception-handle-enabled", matchIfMissing = true)
|
||||
public class SeataExceptionHandlerAdvice {
|
||||
|
||||
@ExceptionHandler({TransactionSystemException.class, RmTransactionException.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public BaseResponse<String> handleTransactionSystemException(HttpServletRequest request,
|
||||
TransactionSystemException exception) {
|
||||
log.info(ExceptionUtil.stacktraceToString(exception));
|
||||
if (((String) Objects.requireNonNull(exception.getMessage())).contains("may be has finished")) {
|
||||
String xid = RootContext.getXID();
|
||||
if (StringUtils.isNotEmpty(xid)) {
|
||||
RootContext.unbind();
|
||||
log.info("TransactionSystemException ----- suspending current transaction,xid = {}", xid);
|
||||
|
||||
return BaseResponse.fail("系统繁忙,请重试", null);
|
||||
}
|
||||
}
|
||||
return BaseResponse.fail("系统异常", exception.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数异常
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
class ArgumentInvalidResult {
|
||||
/**
|
||||
* 字段名
|
||||
*/
|
||||
private String field;
|
||||
/**
|
||||
* 输入的错误值
|
||||
*/
|
||||
private Object rejectedValue;
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String defaultMessage;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user