在上一篇文章《【spring security授权】— 认证/授权简介+简单权限控制》的2.2中简单聊过后端服务器进行权限控制的基本原理,其实spring security对于权限控制的核心原理也是如此,其具体实现方式大致如下图:
接下来看一下授权管理在spring security整个架构中所处的位置:
通过上图的梳理,相信将更有助于大家理解spring security关于认证和授权的整个控制流程。也更容易让大家在阅读spring security源码时,迅速摸清源码的大体骨架。
授权管理的源码有兴趣的可以自己跟一下,我感觉不是很难,这里就不再进行整理了.
首先来看一下,下面的配置:
上面的配置是我们之前代码中的配置,图中第一个适配器 — antMatchers因为调用了permitAll()方法—>访问它所包含的那些url就不需要认证+授权; 第二个适配器因为调用了hasRole()方法 —> 只有有ADMIN权限的用户才能访问它包含的url.那其具体实现原理是什么呢?
跟踪spring security源码时可以很容易发现其秘密,原来如果某个适配器(antMatchers)调用了permitAll()方法,则将该适配器包含的所有URL的权限指定为
一个字符串permitAll
;如果某个适配器(antMatchers)调用了hasRole(“AAA”)方法,则将该适配器包含的所有URL的权限指定为一个字符串hasRole(ROLE_AAA);
如果某个适配器(anyRequest也是一个适配器,表示所有请求)调用了authenticated()方法,则将该适配器包含的所有URL的权限指定为一个字符串authenticated
. 等等等 然后spring security会将项目里所有的url与这些权限字符串放到一个大Map里 —> Map的key为服务器中的各个url,value为permitAll、hasRole(ROLE_AAA)、authenticated等权限字符串的集合.
如下图所示:
当服务器接收到一个请求后,spring security会拿着当前请求去遍历上面所说得url为key,权限字符串集合为value的Map —> 以此找到当前访问URL所需要的用户权限.
一言以蔽之,权限表达式就是一个个标识URL所需访问权限的字符串如permitAll、hasRole(ROLE_AAA)、authenticated等,我们可以在适配器(antMatchers/anyRequest)后调用相应的方法为某个或某些URL指定相应的权限字符串.
除了permitAll、hasRole(ROLE_AAA)、authenticated三个权限表达式(权限字符串)之外,其实还有好多,总结如下:
每个权限表达式都对应一个方法:
注意:
hasRole()方法生成权限表达式的源码如下:
private static String hasRole(String role) {
Assert.notNull(role, "role cannot be null");
if (role.startsWith("ROLE_")) {
throw new IllegalArgumentException("role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'");
} else {
return "hasRole('ROLE_" + role + "')";
}
}
因此如果指定了一个URL的访问权限为hasRole(“ADMIN”)时,该用户应该配置的权限为ROLE_ADMIN
如下面这个需求:
某个URL的访问既需要用户有ADMIN权限,又必须是127.0.0.1这个IP地址发送的请求
权限表达式对应的方法不能进行链式调用,如果想完成此需求,可以使用access()方法拼接权限表达式:
.antMatchers("/user/*").access("hasRole('ROLE_ADMIN') and hasIpAddress('127.0.0.1')")