您现在的位置是:主页 > news > 网站关键字优化公司/网络营销是干什么的

网站关键字优化公司/网络营销是干什么的

admin2025/4/26 20:30:54news

简介网站关键字优化公司,网络营销是干什么的,个人备案域名可以做哪些网站吗,网络营销环境分析文章目录前言GateWay 增加 filter其他服务解析几个工具类前言 跳槽去了新公司,研究公司的系统架构,发现一个很有趣的思路: GateWay 解析前端请求携带的token信息,并向下游微服务传递。 达到下游微服务不用重复解析token&#xff…

网站关键字优化公司,网络营销是干什么的,个人备案域名可以做哪些网站吗,网络营销环境分析文章目录前言GateWay 增加 filter其他服务解析几个工具类前言 跳槽去了新公司,研究公司的系统架构,发现一个很有趣的思路: GateWay 解析前端请求携带的token信息,并向下游微服务传递。 达到下游微服务不用重复解析token&#xff…

文章目录

  • 前言
  • GateWay 增加 filter
  • 其他服务解析
  • 几个工具类

前言

跳槽去了新公司,研究公司的系统架构,发现一个很有趣的思路:

GateWay 解析前端请求携带的token信息,并向下游微服务传递。

达到下游微服务不用重复解析token,就能获取当前登录账户的基本信息

其实原理很简单,但记录下实现方式。

GateWay 增加 filter

在gateway网关服务中,增加filter 过滤器,主要实现获取请求接口中携带的token信息解析token将解析数据继续存放至当前请求对象中

具体实现方式如下所示:

import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CreateCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.net.URI;
import java.util.Date;@Slf4j
@Component
public class UASFilter implements GlobalFilter, Ordered {@CreateCache(name = "uas:user:login:")private Cache<String, String> tokenCache;/*** 1.首先网关检查token是否有效,无效直接返回401,不调用签权服务* 2.调用签权服务器看是否对该请求有权限,有权限进入下一个filter,没有权限返回401** @param exchange* @param chain* @return*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();URI uri = request.getURI();// 判断是否属于白名单中if(white(uri.getPath())){return chain.filter(exchange);}log.debug("**********UASFilter start: " + new Date());try {
//			ServerHttpRequest request = exchange.getRequest();// 获取原始token信息String authentication = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);String method = request.getMethodValue();String url = request.getPath().value();log.debug("url:{},method:{},headers:{}", url, method, request.getHeaders());// 根据环境判断是否校验if (permissionService.ignoreAuthenticationByModule() || isSwaggerUrl(exchange.getRequest().getPath().value())) {return chain.filter(exchange);}//不需要网关签权的urlif (permissionService.ignoreAuthentication(url)) {return chain.filter(exchange);}//登出判断if (isLogout(authentication)) {log.error("已经登出或者在其他设备登录,请重新登录!");return unauthorized(exchange, "已经登出或者在其他设备登录,请重新登录!");}// 核心!!!!!//调用签权服务看用户是否有权限,若有权限进入下一个filterif (permissionService.hasPermission(authentication, url, method)) {ServerHttpRequest.Builder builder = request.mutate();// 原始jwt tokenbuilder.header(GatewayConstans.X_CLIENT_TOKEN, authentication);//将jwt token中的用户信息传给服务builder.header(GatewayConstans.X_CLIENT_TOKEN_USER, permissionService.getUserTokenBase64(authentication));return chain.filter(exchange.mutate().request(builder.build()).build());}return unauthorized(exchange);} finally {log.debug("**********UASFilter end: " + new Date());}}/*** @param token* @return boolean* @throws* @description 登出判断*/private boolean isLogout(String token) {if (StringUtil.isNotEmpty(token) && token.startsWith("Bearer")) {token = token.replace("Bearer", "").trim();String loginToken = tokenCache.get(MD5Util.standardMD5(token));return StringUtil.isBlank(loginToken);}return true;}/*** 网关拒绝,返回401** @param msg*/protected Mono<Void> unauthorized(ServerWebExchange serverWebExchange, String... msg) {DataBuffer buffer = serverWebExchange.getResponse().bufferFactory().wrap(JSON.toJSONBytes(CommonResult.error(HttpStatus.UNAUTHORIZED.value(), "未授权!" + (msg.length > 0 ? msg[0] : ""))));serverWebExchange.getResponse().getHeaders().add("Content-Type", "json/plain;charset=UTF-8");serverWebExchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);log.error("未授权!", msg);return serverWebExchange.getResponse().writeWith(Flux.just(buffer));}@Overridepublic int getOrder() {// 调用优先级, 数字小 优先级高return 20;}
}

其中最为核心的部分在于:

if (permissionService.hasPermission(authentication, url, method)) {// 获取当前的请求对象信息ServerHttpRequest.Builder builder = request.mutate();// 原始jwt tokenbuilder.header(GatewayConstans.X_CLIENT_TOKEN, authentication);// 向header中设置新的key,存储解析好的token对应基本信息builder.header(GatewayConstans.X_CLIENT_TOKEN_USER, permissionService.getUserTokenBase64(authentication));// exchange.mutate().request(builder.build()).build() 将其继续转化为请求对象// 向下游传递return chain.filter(exchange.mutate().request(builder.build()).build());
}

这样,只要请求携带了token,并能够成功解析,就会在请求对象的header数据部分,打上x-client-token-user解析后的数据。

其他服务解析

当gateway网关验证完毕后,合法的请求将会继续向内执行,当进入到对应的模块时,此时只需要从请求中获取x-client-token-user对应的登录账户解析数据,并将其保存至ThreadLocal中即可。

一样可以使用filter 过滤器,使用拦截器也可以!

核心代码如下所示:

import org.springframework.web.filter.OncePerRequestFilter;@Order(-1000)
@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {// 重写  doFilterInternal  方法即可protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {// 获取请求中header的 x-client-token-user信息String userToken = httpServletRequest.getHeader("x-client-token-user");if (userToken != null) {String json = EncryptUtil.decodeUTF8StringBase64(userToken);JSONObject jsonObject = JSON.parseObject(json);HashMap profile = (HashMap)JSON.parseObject(jsonObject.getString("user_name"), HashMap.class);// 这里是 ThreadLocal 的封装,将获取到的数据存放其中UserContextHolder.getInstance().setContext(profile);} else {UserContextHolder.getInstance().setContext(this.getParamMap());}filterChain.doFilter(httpServletRequest, httpServletResponse);}
}

在需要使用的地方,采取下列方式获取即可:

public static Profile getProfile() {Map<String, String> data = UserContextHolder.getInstance().getContext();if (null == data) {throw new RuntimeException("当前请求没有通过网关监控,无法加载登录用户信息!");} else {Profile profile = (Profile)BeanUtil.toBean(data, Profile.class);logger.debug("当前登陆用户信息:{}", profile.toString());return profile;}
}

几个工具类

UserContextHolder .java

import java.util.Map;public class UserContextHolder {private ThreadLocal<Map<String, String>> threadLocal;private UserContextHolder() {this.threadLocal = new ThreadLocal();}public static UserContextHolder getInstance() {return UserContextHolder.SingletonHolder.sInstance;}public void setContext(Map<String, String> map) {this.threadLocal.set(map);}public Map<String, String> getContext() {return (Map)this.threadLocal.get();}public void clear() {this.threadLocal.remove();}private static class SingletonHolder {private static final UserContextHolder sInstance = new UserContextHolder();private SingletonHolder() {}}
}