目录

思路分析

会话保持

步骤


思路分析

1.用户通过访问微服务网关调用微服务,同时携带头文件信息

2.在微服务网关这里进行拦截,拦截后获取用户要访问的路径

3.识别用户访问的路径是否需要登录,如果需要,识别用户的身份是否能访问该路径[这里可以基于数据库设计一套权限]

4.如果需要权限访问,用户已经登录,则放行

5.如果需要权限访问,且用户未登录,则提示用户需要登录

6.用户通过网关访问用户微服务,进行登录验证

7.验证通过后,用户微服务会颁发一个令牌给网关,网关会将用户信息封装到头文件中,并响应用户

8.用户下次访问,携带头文件中的令牌信息即可识别是否登录

会话保持

用户每次请求的时候,我们都需要获取令牌数据,方法有多重,可以在每次提交的时候,将数据提交到头文件中,也可以将数据存储到Cookie中,每次从Cookie中校验数据,还可以每次将令牌数据以参数的方式提交到网关,这里面采用Cookie的方式比较容易实现。

步骤

  • 登录封装Cookie
/***    *用户登录    */   
@RequestMapping(value = "/login")   
public Result login(String username, String password, HttpServletResponse response){     
//查询用户信息     
User user = userService.findByUsername(username);

    if(user!=null && BCrypt.checkpw(password,user.getPassword())){

        //设置令牌信息       
        Map<String,Object> info=new HashMap<>();       
        info.put("role","USER");       
        info.put("success","SUCCESS");       
        info.put("username",username);       
        //生成令牌       
        String jwt = JwtUtil.createJWT(UUID.randomUUID().toString(),         
                     JSON.toJSONString(info), null);

        //创建Cookie对象       
        Cookie cookie = new Cookie("Authorization",jwt);       
        //设置cookie的路径           
        cookie.setPath("/");       
        //把cookie使用响应头设置给浏览器       
        response.addCookie(cookie);        

        return new Result(true,StatusCode.OK,"登录成功!",jwt);     
    }     
    return new Result(false,StatusCode.LOGINERROR,"账号或者密码错误!");   
}
  • 修改user微服务,每次登录的时候,添加令牌信息到Cookie中,修改dongyimai-user-service的com.offcn.user.controller.UserControllerlogin方法
  • 过滤器获取令牌数据
• package xin.yi.filter;
import io.jsonwebtoken.Claims; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpCookie; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import xin.yi.utils.JwtUtil;
/**• @program: dongyimai-parent
• @description:
• @author: xin yi
• @create: 2021-08-14 21:24 */ @Component public class AuthorizeFilter implements GlobalFilter, Ordered {
/设置令牌头名字/ private static final String AUTHORIZE_TOKEN = "Authorization";
/**• 全局过滤器
• @param exchange
• @param chain
• @return / @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { /设置Request、Response对象*/ ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse();
/获取请求的URI/ String path = request.getURI().getPath();
/**• 如果是登录、goods等开放的微服务[这里的goods部分开放],则直接放行,这里不做完整演示,完整演示需要设计一套权限系统 / if (path.startsWith("/api/user/login") || path.startsWith("/api/brand/search/")){ /放行*/ Mono<Void> filter = chain.filter(exchange); return filter; }
/获取头文件中的令牌信息/ String tokent = request.getHeaders().getFirst(AUTHORIZE_TOKEN);
/**
• 如果头文件中没有,则从请求参数中获取 */ if (StringUtils.isEmpty(tokent)){ tokent = request.getQueryParams().getFirst(AUTHORIZE_TOKEN); }
   /**
     * 从cookie中获取令牌数据
     */
    HttpCookie first = request.getCookies().getFirst(AUTHORIZE_TOKEN);
    if (null != first){
        tokent = first.getValue();
    }

    /**
     * 如果为空,则输出错误代码
     */
    if (StringUtils.isEmpty(tokent)){
        /*设置方法不允许被访问,405错误代码*/
        response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED);
        return response.setComplete();
    }

    /**
     * 解析令牌数据
     */
    try {
        Claims claims = JwtUtil.parseJWT(tokent);
        /*在令牌信息校验那块将令牌加入到请求头中*/
        request.mutate().header(AUTHORIZE_TOKEN,claims.toString());
    } catch (Exception e) {
        e.printStackTrace();
        /*解析失败响应401错误*/
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }

    /*放行*/
    return chain.filter(exchange);
}
/**
 * 过滤器执行顺序
 * @return
 */
@Override
public int getOrder() {
    return 0;
}
}
  • 每次在网关中通过过滤器获取Cookie中的令牌,然后对令牌数据进行解析,修改微服务网关dongyimai-gateway-web中的AuthorizeFilter
  • 添加Header信息
• Claims claims = JwtUtil.parseJWT(token); //把解析出来的令牌添加到头文件中 request.mutate().header(AUTHORIZE_TOKEN,claims.toString());
• 我们还可以在Gateway的全局过滤器中添加请求头信息,例如可以将令牌信息添加到请求头中,在微服务中获取头信息
//获取请求头中封装的令牌     String token = request.getHeader("Authorization");     System.out.println("令牌信息:"+token);