restful接口权限控制及其灵活授权

  • 由于restful风格接口路径中带有变量,使得权限控制成为一大难题,官方的各种权限框架比较复杂,一时间可能难以用的得心应手,给一些中小型项目转前后端分离带来一定的难度。
  • 日常业务中,权限一般都需要能动态配置,本篇博客采用RBAC设计原则对系统的的权限进行设计。
  • 核心思想是控制controller中方法的访问权限,将【类名】.【方法名】映射为一个资源,对该资源进行动态授权。
  • 授权服务可以单独写一个项目作为授权中心(微服务),也可以集成到项目中(单体应用)。
  • 用户登录时验证用户名密码是否正确,正确后验证token表中是否已经登录过,如果已经登录则直接返回之前的token,
    生成token保存数据库,同时使用生成的token作为key在redis中缓存已登录用户的信息,
    用户登出只需清除redis和数据库中的token信息即可,这样也可以在服务端强制下线某个用户。

表设计

用户表(sys_user):
字段名数据类型长度必须索引备注
idbigintprimary key用户表主键
usernamevarchar255unique用户名,唯一索引
passwordvarchar255密码编码后的密码
emailvarchar255邮箱
last_logindatetime最后登录时间
登录Token表(sys_token)
字段名数据类型长度必须索引备注
idbigintprimary key主键
uidbigintunique登录用户id
tokenvarchar255uniquetoken,唯一索引
refresh_tokenvarchar255unique刷新token(用户发出刷新请求时重置登录时间为当前时间)
expirationbigint有效时间(毫秒)
login_timedatetime登录时间
角色组(sys_role_group):
字段名数据类型长度必须索引备注
idbigintprimary key角色组表主键
user_group_namevarchar255角色组名
角色表(sys_role):
字段名数据类型长度必须索引备注
idbigintprimary key角色表主键
role_namevarchar255角色名
rule_codevarchar255unique角色编码,唯一索引
group_idbigint所属组
用户角和色组关联表(sys_user_role_group):
字段名数据类型长度必须索引备注
uidbigintindex用户id
gidbigintindex组id
用户角色关联表(sys_user_role):
字段名数据类型长度必须索引备注
uidbigintindex用户id
ridbigintindex角色id
接口权限表(sys_interface)
字段名数据类型长度必须索引备注
idbigintprimary key主键id
class_namevarchar255unique index包名+类名(考虑到不同系统类名可能重复)
method_namevarchar255unique index方法名称
request_typetinyintunique index请求类型(1:get, 2:post,3:put,4:delete)
接口权限角色关联表(sys_interface_role):
字段名数据类型长度必须索引备注
interface_idbigintindex接口id
ridbigintindex角色id

当然,不是很复杂的系统可以考虑不使用组设计,用户直接和角色关联

/**
 * 在项目中添加一个拦截器
 * 获取请求的方法和
 */
@Configuration
public class AuthorizaionInterceptor implements HandlerInterceptor {

	// 配置文件中配置的请求头中获取token的名称,默认为:Authorization
 	@Value("${token.name:Authorization}")
    private String tokenName;

	@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws 	Exception {
    	// 判断是否请求的controller中的请求
        if (handler instanceof HandlerMethod) {
        	// 获取token
            String token = request.getHeader(tokenName);
        	// 强制类型转换
            HandlerMethod h = (HandlerMethod) handler;
            // 获取请求的方法名称
            String methodName = h.getMethod().getName();
            // 获取请求的Controller类全名称(包名+类名)
            String className = h.getMethod().getDeclaringClass().getSimpleName();
            // 在这进行数据库或redis缓存验证登录用户是否具有访问权限
            /*
            	登录时对用户所拥有的权限生成一个对象保存到redis中,key为token
            	在此处进行校验时直接从redis中取对象,如果取不到去数据库中根据token查询是否登录,
            	如果没查到则为无效token
            	如果查到则进行过期判断,如果过期则无效
            	如果合法则判断是否拥有权限
            	有则通过,没有则response返回401提示没有权限
            */
            System.out.printf("请求Controller ==》 %s.%s\n", className, methodName);
            return true;
        } else {
            return true;
        }
    }
}

欢迎关注我的微信公众号,每天分享一点点,每天进步一点点
阿里桃子的技术栈

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值