import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
@Configuration
public class CorsConfig {
/**
* 该访问配置跨域访问执行
*/
@Bean
public CorsWebFilter corsWebFilter() {
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
//cors跨域配置对象
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);//是否允许携带cookie
corsConfiguration.addAllowedOrigin("*"); //允许跨域访问的域名,可填写具体域名,*代表允许所有访问
corsConfiguration.addAllowedMethod("*");//允许访问类型:get post 等,*代表所有类型
corsConfiguration.addAllowedHeader("*");
//配置源对象
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
//cors 过滤器对象 注意!CorsWebFilter不要导错包
return new CorsWebFilter(urlBasedCorsConfigurationSource);
}
}
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.HandlerExceptionResolver;
@Slf4j
@Order(1)
public class UserSessionFilter extends OncePerRequestFilter {
@Autowired
@Qualifier("handlerExceptionResolver")
private HandlerExceptionResolver resolver;
@Autowired
private CommonRedisService commonRedisService;
@Autowired
private YmlConfig ymlConfig;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
log.info("====== UserSessionFilter =======");
String uri = request.getRequestURI();
log.info("uri: {}", uri);
//无需登录的接口
if (ymlConfig.getUnLoginUrlList().contains(uri)) {
filterChain.doFilter(request, response);
return;
}
//校验session
HttpSession session = request.getSession(false);
//游客放行但需要用户信息接口
if (null == session && ymlConfig.getUnLoginNeedUserInfoUrlList().contains(uri)) {
filterChain.doFilter(request, response);
return;
}
if (null == session) {
//提示重新登录
resolver.resolveException(request, response,
null, new BusException(ErrorCodeEnum.USER_SESSION_ERROR, ErrorEnum.USER_SESSION_IS_ERROR));
return;
}
Long userId = (Long) session.getAttribute(GlobalConst.USER_ID_STR);
String loginSessionidKey = RedisKeyConst.USER_LOGIN_SESSIONID_KEY + userId;
String loginSessionid = null != userId ? (String) commonRedisService.getValue(loginSessionidKey) : null;
// userId为null表示当前客户端没有登录,redis 的Sessionid与当前 Sessionid不相等表示多端登录
if (null == userId || StringUtils.isBlank(loginSessionid) ||
ymlConfig.isEnnableLoginMany() ? false : !session.getId().equals(loginSessionid)) {
//提示重新登录
resolver.resolveException(request, response,
null, new BusException(ErrorCodeEnum.USER_SESSION_ERROR, ErrorEnum.USER_SESSION_IS_ERROR));
return;
}
//session中获取
String roleIdsJsonStr = session.getAttribute(GlobalConst.ROLE_ID_LIST_STR).toString();
List<Integer> roleIds = JSON.parseArray(roleIdsJsonStr, Integer.class);
UserRoleInfo userRoleInfo = new UserRoleInfo();
userRoleInfo.setUserId(userId);
userRoleInfo.setRoleIds(roleIds);
//保存用户信息到ThreadLocal
UserRoleInfoUtil.set(userRoleInfo);
//放行
try {
filterChain.doFilter(request, response);
} finally {
UserRoleInfoUtil.clear();//清除
}
}
}
public class UserRoleInfoUtil {
private static final ThreadLocal<UserRoleInfo> currentUser = new ThreadLocal<>();
public static UserRoleInfo get() {
return currentUser.get();
}
public static void set(UserRoleInfo userRoleInfo) {
currentUser.set(userRoleInfo);
}
public static void clear() {
currentUser.remove();
}
}
@EnableRedisHttpSession的使用,UserSessionFilter作为公共代码,以@Import的注册方式加入到需要Sesssion校验的微服务模块之中。
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.session.FlushMode;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@Slf4j
@EnableRedisHttpSession(
maxInactiveIntervalInSeconds = 28800,
flushMode = FlushMode.ON_SAVE,
redisNamespace = "spring:session:xxx.web.user")
@MapperScan("xxx.web.order.infrastructure.mapper")
@SpringBootApplication(scanBasePackages = {"xxx.web.order", "xxx.web.common"})
@EnableFeignClients(basePackages = "xxx.web.user.client.feign")
@Import(UserSessionFilter.class)
@EnableAspectJAutoProxy(exposeProxy=true)
public class OrderApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Override
public void run(String... args) {
log.info("----------------------OrderApplication Start Success----------------------");
}
}