接上一篇的权限控制,再讨论再网关zuul的登录认证实现。

网关使用SpringCloud的zuul,登录认证选择使用自定义共享session的方式,来实现集群的登录验证。保护接口的私密,保证系统安全。

Filter

zuul提供了filter来对请求进行过滤处理,首先,了解网关zuul的filter。

zuul的filter有三种类型的,pre,route,post,error,static。

  • pre,在路由之前的过滤
  • route,是在pre之后,路由过程中过滤
  • post,是在route之后,结果返回之前过滤
  • error,异常处理,在异常之后过滤
  • static,配置一组URL,返回静态资源,不路由到后端服务

因为登录验证在网关接受到请求之后就要做的,所以在prefilter中增加登录验证的逻辑。

请求Header

cookies和特殊的http请求headers

使用共享session的方式,后端服务必然也要使用用户的缓存数据,这就需要将用户标识传递给后端服务,通过http请求Header传递,将用户请求的Cookie或者特殊的http请求headers(取决于自己的需要)传递给网关后面的业务服务。zuul提供了配置zuul.sensitiveHeaders来配置需要传递给后端服务的请求头。如:

zuul:

sensitive-headers: Cookie,Set-Cookie

登录

要登录验证,首先需要登录,登录如何实现呢。

验证用户登录信息有效性后,生成token,存储用户token到redis中,作为有效token,同时将用户的缓存信息存入redis中。

redis中数据存储结构为两个键值对

  • 键为用户token,值为用户数据,实现token有效性,用户数据缓存功能。
  • 键为用户ID,值为用户token,可以通过用户ID查询用户token,实现立刻失效用户token功能。

样例代码如下:

public Map<String, Object> login(String userId, String password) {//验证用户登录信息有效性Boolean result = validate(userId, password);Map<String,Object> map = new HashMap<>();//存储两个键值对,一个是token和用户数据的键值对,第二个是用户id和token的键值对,实现通过用户ID找到用户的token,实现即刻失效用户token的功能。根据需求,也可以只存储一个。if(result){String body = getUser(userId);String sessionKey = SESSION_PREFIX+"_"+sessionId;String userKey = USER_ID_PREFIX+"_"+userId;redisTemplate.opsForValue().set(sessionKey, userId, EXPIRE_SECOND, TimeUnit.SECONDS);redisTemplate.opsForValue().set(userKey, sessionId, EXPIRE_SECOND, TimeUnit.SECONDS);redisTemplate.opsForValue().set(dataKey, body, EXPIRE_SECOND, TimeUnit.SECONDS);map.put("code","0");map.put("msg","ok");return map;}map.put("code","0");map.put("msg","用户名或密码错误");return map;
}

登录验证

考虑到登录验证的时候,还有隐藏的其他可能需要的功能。

  1. 某些接口不需要不进行登录验证,如登录,注册,获取验证码等接口。
  2. 某些接口需要登录验证,但是不需要刷新token有效时间,如客户端轮询请求的接口。
  3. 特定场景下IP黑、白名单。
  4. 处于安全考虑的接口流量控制。

考虑将最基本的第一个和第二个功能加入进来,其他的后续再实现。

增加1,2需求后登录认证的流程如下

通常需要登录验证的接口列表,不刷新token有效时间的接口列表都通过配置来实现,这里不再赘述。

登录认证代码如下:

@Component
public class PreFilter {public static final Logger log = LoggerFactory.getLogger(PreFilter.class);@Autowiredprivate RedisTemplate redisTemplate;@Value("${server.context-path}")private String contextPath;@Value("${auth.session.expireSecond}")private Integer expire;@Overridepublic String filterType() {return "pre";}@Overridepublic int filterOrder() {return 1;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() throws ZuulException {// 得到Rquest ResponseRequestContext ctx = RequestContext.getCurrentContext();HttpServletRequest req = ctx.getRequest();HttpServletResponse res = ctx.getResponse();try {String uri = req.getRequestURI();//得到SessionIdString sessionId = req.getSession(true).getId();//是否登录认证Boolean isIgnore = isIgore(uri);if(isIgnore){ctx.setSendZuulResponse(true);// 对该请求进行路由ctx.setResponseStatusCode(200);return null;}//是否刷新session过期时间Boolean isRefreshExpire = isRefreshExpire(uri);Boolean isLogin = false;if(isRefreshExpire){// 检查过期时间并刷新isLogin = checkLoginWithExpire(sessionId);}else{// 检查过期时间isLogin = checkLoginWithoutExpire(sessionId);}//认证成功if(isLogin){ctx.setSendZuulResponse(true);// 对该请求进行路由ctx.setResponseStatusCode(200);return null;}//认证失败Map<String,Object> result = new HashMap<>();result.put("code","1");result.put("msg","请登录");ctx.getResponse().setContentType("application/json;charset=utf-8");ctx.setSendZuulResponse(false);ctx.setResponseStatusCode(401);ctx.setResponseBody(JSON.toJSONString(result));// 返回错误内容return null;} catch (NoSuchAlgorithmException e) {log.error("generatePVID error", e);}return null;}/*** 是否登录认证* @param uri 请求接口标志* @return*/private Boolean isIgore(String uri) {String s = uri.replaceAll(contextPath,"");for(String reg : ZuulInit.getIgnoreUrl()){if(s.matches(reg)){return true;}}return false;}/*** 是否刷新过期时间* @param uri* @return*/private Boolean isRefreshExpire(String uri){String s = uri.replaceAll(contextPath,"");for(String reg : ZuulInit.getExpireUrl()){if(s.matches(reg)){return true;}}return false;}/*** 检查过期时间,并刷新过期时间* @param sessionId* @return*/private Boolean checkLoginWithExpire(String sessionId){String key = SESSION_PREFIX + domain + "_" + sessionId;String userId = (String)redisTemplate.opsForValue().get(key);String userKey = USER_PREFIX + "_" + userId;String dataKey = DATA_PREFIX + "_" + sessionId;if(!StringUtil.isEmpty(userId)){Boolean r = redisTemplate.expire(key, expire,TimeUnit.SECONDS);//刷新时间没有成功,返回认证不通过if(!r){return false;}r = redisTemplate.expire(userKey, expire, TimeUnit.SECONDS);if(!r){return false;}r = redisTemplate.expire(dataKey, expire, TimeUnit.SECONDS);if(!r){return false;}return true;}return false;}/*** 检查过期时间* @param sessionId* @return*/private Boolean checkLoginWithoutExpire(String sessionId){String key = SESSION_PREFIX + domain + "_" + sessionId;String userId = (String)redisTemplate.opsForValue().get(key);if(!StringUtil.isEmpty(userId)){return true;}return false;}

如上代码只是一个简单的功能实现,还需要在此基础上面向对象的设计、优化等考虑。

(完)

微服务权限控制(二)共享Session方式的登录认证相关推荐

  1. SpringCloud微服务权限控制(一)概述

    从单体应用到SOA应用再到Spring Cloud微服务构架,应用的安全访问都是非常重要的问题,怎么样设计微服务的权限控制?首先,权限控制可以分为三个部分:用户认证,服务权限,用户权限. 用户认证 用 ...

  2. Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战

    本文源码地址 后端:https://gitee.com/youlaitech/youlai-mall/tree/v2.0.1 前端:https://gitee.com/youlaiorg/mall-a ...

  3. 微服务接入oauth2_微服务权限终极解决方案,Spring Cloud Gateway+Oauth2实现统一认证和鉴权!...

    最近发现了一个很好的微服务权限解决方案,可以通过认证服务进行统一认证,然后通过网关来统一校验认证和鉴权.此方案为目前最新方案,仅支持Spring Boot 2.2.0.Spring Cloud Hox ...

  4. .NET Core微服务 权限系统+工作流(二)工作流系统

    一.前言 接上一篇 .NET Core微服务 权限系统+工作流(一)权限系统 ,再来一发 工作流,我在接触这块开发的时候一直好奇它的实现方式,翻看各种工作流引擎代码,探究其实现方式,个人总结出来一个核 ...

  5. springcloud 微服务鉴权_springcloud 微服务权限校验JWT模式获取 token 实战(十二)...

    springcloud 微服务权限校验JWT模式获取 token 实战(十二) springcloud 微服务权限校验JWT模式获取 token 实战(十二) JWT:json web token 是 ...

  6. Spring Security系列(10)- 微服务权限方案及Oauth2介绍

    微服务 什么是微服务 微服务由来 微服务最早由 Martin Fowler 与 James Lewis 于 2014 年共同提出,微服务架构风格是一种使用一套小服务来开发单个应用的方式途径,每个服务运 ...

  7. Spring Cloud下微服务权限方案

    背景 从传统的单体应用转型Spring Cloud的朋友都在问我,Spring Cloud下的微服务权限怎么管?怎么设计比较合理?从大层面讲叫服务权限,往小处拆分,分别为三块:用户认证.用户权限.服务 ...

  8. 学习笔记:带你十天轻松完成 Go 微服务系列(二)- 服务拆分

    学习笔记:带你十天轻松搞定 Go 微服务系列(二) 1.学习课程 2.服务拆分 2.1 按业务服务拆分 2.2 按调用方式拆分 3.创建项目目录 3.1 在 code 中新建项目 3.2 创建 mal ...

  9. 微服务权限终极解决方案(spring-cloud-gateway-oauth2)

    spring-cloud-gateway-oauth2 前言 我们理想的微服务权限解决方案应该是这样的,认证服务负责认证,网关负责校验认证和鉴权,其他API服务负责处理自己的业务逻辑.安全相关的逻辑只 ...

最新文章

  1. 如果服务器开机显示NObootable,电脑不能开机提示No bootable device怎么办?
  2. linux 网络通讯 命令,Linux—网络通讯管理命令
  3. gmock学习01---Linux配置gmock
  4. leetcode--872. 叶子相似的树
  5. 还在用背单词App?使用Python开发英语单词自测工具,助你逆袭单词王!
  6. linux--exec函数族浅析
  7. 9月30日skype事件
  8. 百度SEO站群WeLive免费在线客服系统 v5
  9. C++解决程序一闪而退及清屏函数
  10. 计算机在表格顶端添加标题,Excel表格图标上方显示数据-怎样在excel图标里添加图表元素?...
  11. wps斜杠日期格式_wps表格,怎样将输入的日期间隔斜线改为横线?
  12. HTML+CSS一篇文章搞定
  13. python -m的那些实用功能
  14. 学生宿舍管理mysql设计_学生宿舍管理系统设计与实现(SSH,MySQL)
  15. Java代码修改文件后缀名
  16. HtmlUnit的简单例子
  17. 运维 —— 1521端口不通
  18. 城镇水务系统碳减排路径|雨水系统
  19. 学好单片机好找工作吗?单片机学到什么程度可以找工作?
  20. arcgis 导入 GML文件

热门文章

  1. sql server 2008新特性:资源调控器
  2. 布隆过滤器误判_布隆过滤器原理
  3. autoreconnect mysql true_使用’autoReconnect = true’即使MySql JDBC超时
  4. 2021柳州市地区高考成绩排名查询,2021年柳州所有高中排名一览表
  5. 4地形编辑插件_SketchUp高效建模插件
  6. mysql suoyin 和锁_mysql 索引和锁
  7. 色彩搭配总是显得很乱?配色专辑把色彩简单化
  8. 淘宝京东设计师来看,电商Banner设计策略!
  9. UI设计干货素材|简单素材模板教你分分钟提高UI设计水平!
  10. 刚入行的UI设计师,通过临摹优秀UI KIT作品开始