使用 token 怎么做权限控制的呢?

在不使用 shiro、spring security 的情况下, 现在很多系统对移动端说是用 jwt(json web token) 弱弱的问下,
使用jwt 你们是怎么做权限控制的呢? 怎么判断一个用户是否有权限访问该接口?

后台怎么配置?
 
换个问法  没有shiro、spring security 的话,你怎么表达每个入口方法的所需要的权限?
 
已邀请:

黑暗游侠

赞同来自: jamen katch Marco xiaobaxi Mr_阳

分享一下最近刚刚完成的restfull 接口权限控制方案,欢迎大家拍砖。
Spring Security、Spring Cloud Security都有完整的权限解决方案,可是我们的需求是需要对每个微服务的提供接口具有动态权限的能力,以及考虑到将来项目模块外包技术栈的多样性决定自己封装一套简单的权限控制模块。 
1、如何动态控制接口权限?最经典的权限模型为 用户-角色-权限,对于restfull 接口权限控制就是要表达出对于当前请求用户以及用户所属的角色是放行还是拒绝。为此我参照Spring Security 设计了u_intercept_url 表

111.png


method 字段描述了接口请求的方法GET、POST 、PUT、 PATCH、 DELETE  ALL表示所有方法
channel 字段描述接口请求的协议 如 HTTP 、HTTPS、 TCP 等 ANY表示所有协议
access 字段描述此接口的访问限制ROLE_开头表示此接口的角色限制,USER_开头表示此接口的用户限制
 
为了减少后续的维护量无需新增一个无特殊权限接口就需要配置到u_intercept_url表添加了

1 /api-*/** ALL ROLE_USER,ROLE_DEALER ANY 允许所有用户和经销商访问所有资源 0 0 admin 2017-05-17 17:19:14 admin 2017-05-17 17:19:18
记录。
 
2、使用JWT放置用户和角色信息
在用户获取的jwt token的载荷中放置了如下属性
{"sub":163,"audience":"web","created":1496304597273,"roles":"USER","exp":1496909397}

sub 表示用户ID
roles 表示用户角色,有多个角色用,隔开
 
当前用户角色有更新后,在响应头中添加参数NEED_REFRESH_TOKEN=true ,客户端在发现有此参数后调用刷新token接口可以更新jwt token载荷中的roles字段
 
3、在过滤器中放置权限判断逻辑(zuul可以放在路由过滤器中pre中)
判断核心代码如下
 //判断登录用户的资源权限
for (RkInterceptUrl permission : allRkInterceptUrl) {
path = permission.getPattern();
method = permission.getMethod();
access = permission.getAccess();
matcher = new AntPathRequestMatcher(path);

if (matcher.matches(mRkJwtAuthorizationInfo.getRequest()) &&
(method.equals(mRkJwtAuthorizationInfo.getRequest().getMethod()) || "ALL".equals(method))) {

if (access != null) {
//能够匹配URL,都将授权状态改成未通过
authOk = false;
String[] accessList = access.split(",");
for (String anAccessList : accessList) {
String accessItem = anAccessList;
//url拦截规则表配置了对角色的限制
if (accessItem.startsWith(Constants.INTERCEPT_URL_ACCESS_ROLE_PREFIX)) {

accessItem = accessItem.substring(Constants.INTERCEPT_URL_ACCESS_ROLE_PREFIX.length());

for (String role : roles) {
if (accessItem.equals(role)) {
authOk = true;
break;
}
}

}
}
if (!authOk) {
throw new RkForbiddenException("Forbidden", HttpStatus.FORBIDDEN.value());
}
}

}
}

 
 
 
 
 
 
 
 
 
 
 

泥瓦匠BYSocket - bysocket.com

赞同来自: fishinhouse

token 就类似 sessionid
通过token,获取到用户 A ,然后根据权限映射(可能存 db)(比如简单地 URL 和 用户映射),获取到 用户 A 地权限列表。然后根据权限列表查看这个 url 对这个用户 A 是否有权限即可。

ptzhuf

赞同来自: lj19950508

用jwt存放用户权限, jwt本身是无状态的, 那么用户权限发生了变化怎么办? 
明明管理员刚给用户A增加了一个菜单的权限, 但是用户却访问不了
 
 
如果是每个请求都动态验证用户权限, 那么也就没有了把用户权限放在jwt里的必要!

杨小强 - http://www.jianshu.com/u/997ed7c05f59

赞同来自: chenssy

我觉得用token做权限控制不太好,用token做权限控制的话,需要要用户的权限数据封装到token里面(token本身应该只有用户信息),而token是每一次前后端交互要携带的,所以说这样是不合理的

jamen - 90后iT

赞同来自:

用restfull 风格, 仅仅是 方法类型不一样, url应该是一样的,

还有就是 htt://xxx/spring4all/menu/{id}/user/{id} 这样类型的 url ,
 
实在找不到一个好的办法来判断这个token 或者这个 url 对这个用户是有权限的。

泥瓦匠BYSocket - bysocket.com

赞同来自:

jwt

devzxd

赞同来自:

将用户权限放在jwt中,在拦截器中做权限校验

xiaobaxi - Fang Oba

赞同来自:

jwt的token发放,大家是怎么做的呢?

ed34

赞同来自:

-----当前用户角色有更新后,在响应头中添加参数NEED_REFRESH_TOKEN=true. 
怎么做到的?如果采用类似黑名单的方式,在服务器端每次解开jwt获取用户名后都去比对是否在名单中,会不会失去了jwt的优势?

yuechen323

赞同来自:

都用jwt了, 那必定是前后端分离了
login操作
1. server端: redis中存储用户会话+所有权限编码, 返回给client 内容为: jwt + 所有权限编码
(tips: 权限编码就是页面上的菜单按钮对应的标识, 因此一楼那个返回role一点意义都没有, 客户端知道role毫无用处, 目的不就是为了显示和隐藏菜单/按钮吗)
 
2. client端: 将jwt+权限编码都存储到localStorage中, 并开发通用发送request的function, 为了统一在request里面加上localStorage的jwt
 
3. client后续请求, 每次都发请求带着jwt
 
4. server验证
1) 验证会话: 用Filter实现, 在里面判断jwt是否合法, 同时支持是否需要会话的一个url配置, 比如忘记密码就不需要会话
2)验证权限: 用AOP实现, 在相应controller方法前面添加相应的自定义注解@RequirePriv("权限编码1", "权限编码2"), 然后每次请求先Filter验证会话通过后, 进入这个AOP切面, 验证用户权限是否存在,  验证方式就是去redis里面看看他有没有这个权限编码
 
 
tips: 权限动态更新, 管理员给这个用户更新权限后, 同步更新这个人在redis中记录的权限编码, 然后通知客户端的部分 用websocket实现, 这一个websocket通道中的功能包括, 更新浏览器localStorage中的权限, 接受通知,聊天等通知类的功能
 
 

zhuoxiuwu - Andorid Java python

赞同来自:

我的理解是这样的:
token存权限信息就不需要去redis查询用户的权限,如果token总不存用户权限,则每个需要权限验证的api调用,都需要先去 缓存查询出用户对应的权限再做判断。由于token有签名机制,用户是无法伪造权限的,所以可以认为是安全的

要回复问题请先登录注册