restful项目的权限控制实现技巧

前言

最近的项目在用restful风格在写,果然url都有了意义,功能都可以从url中推测出来,restful的url和非restful的url最大的一个感官区别就是,rest的url可能存在一些变量,比如下面这样:/check/api/user/12345/history,这个url解释起来就是:查看账号为12345的用户的历史资料,而非rest的url是:/check/api/user/history。那么,现在问题就来了,权限控制的核心是判断url,rest的url中却有变量,那么,rest风格的项目如何实现权限控制呢?

实现

其实在我我写这篇文章之前,我的思路是把url的变量去掉,然后存权限表中,然后判断的时候就把访问的url按照相同的规则处理,再在数据库中查,如果查到了代表有权限,反之没有。但事实证明,这种思路只有在变量在url的结尾时才可行。

首先我贴一下权限表的结构,这个是权限控制的核心表。

-- Create table
create table STAFF_POWER
(
  stp_id      NUMBER not null,
  stp_name    VARCHAR2(40),
  create_time TIMESTAMP(6),
  stp_url     VARCHAR2(100),
  stp_method  VARCHAR2(10)
)
tablespace CHECK_ZS
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
-- Create/Recreate primary, unique and foreign key constraints 
alter table STAFF_POWER
  add constraint STP_PK primary key (STP_ID)
  using index 
  tablespace CHECK_ZS
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
alter table STAFF_POWER
  add constraint STP_UN unique (STP_URL, STP_METHOD)
  using index 
  tablespace CHECK_ZS
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
  );
每个字段的意思我解释一下,id是主键,name是这条权限的名字,time是创建时间,由系统自动生成,url是url,method是访问方式。

然后比较关键的一点就来了,url存的时候将变量全部换成%,为什么这样呢,先看下我判断权限的sql:

<select id="selectByUrlAndMethod" resultMap="BaseResultMap" parameterType="java.lang.String">
    select *
    from STAFF_POWER
    <where>
    	and STP_METHOD = #{method}
   		and #{url} like STP_URL 
    </where>
  </select>
我用的mybatis。

权限拦截器的核心代码如下:

StaffPower power=powerSer.selectByUrlAndMethod(url, method);
		if (power!=null) {
			boolean isPass=role.getPowers()!=null && (","+role.getPowers()+",").contains(","+power.getStpId()+",");
			if (isPass==false) {
				Result<String> result=new Result<String>(BaseRestController.ERROR, Code.ROLE_NO_PERMISSION, "您没有权限,请联系管理员");
				PrintWriter pw=resp.getWriter();
				pw.print(gson.toJson(result));
				pw.flush();
				pw.close();
				return false;
			}
			return isPass;
		}else{
			log.error("没有这个权限   "+url+"  "+method);
			Result<String> result=new Result<String>(BaseRestController.ERROR, Code.PERMISSION_NO_EXIST, "该模块还没有设计权限,暂时不能操作");
			PrintWriter pw=resp.getWriter();
			pw.print(gson.toJson(result));
			pw.flush();
			pw.close();
			return false;
		}


现在数据库中有这样一条权限:


我现在想看历史,于是访问 /check/api/sourceTp/3803140612558/history,然后sql是怎么执行的呢,下面是执行的结果:


[2017-05-11 10:09:54.400] - [DEBUG] [http-nio-8080-exec-9  :17561] ==>  Preparing: select * from STAFF_POWER WHERE STP_METHOD = ? and ? like STP_URL 
[2017-05-11 10:09:54.400] - [DEBUG] [http-nio-8080-exec-9  :17561] ==> Parameters: GET(String), /check/api/sourceTp/3803140612558/history(String)
[2017-05-11 10:09:54.403] - [DEBUG] [http-nio-8080-exec-9  :17564] <==      Total: 1

看到这里,它的原理应该就很清楚了,权限控制核心是url+method的判断,而rest的url比较特别从而导致无法像原来那样判断,于是我把所有的变量替换为%,而%是sql模糊查询的符号,所以就刚好可以借用sql的模糊查询来完成判断(中间不做任何处理)。

总结

判断的核心是url+method,但最最核心(而且好多人都没想到这种方法)的是使用%,%代表任意。



  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值