自定义用户访问控制
实际生产中,网站访问多是基于HTTP请求的,我们已经进行MVC Security安全配置介绍时,已经分析出通过重写WebSecurityConfigurerAdapter类的configure(HttpSecurity http)方法可以对基于HTTP的请求访问进行控制。下面,通过对configure(HttpSecurity http)方法的探索来讲解自定义用户访问控制的实现。
configure(HttpSecurity http)方法中的参数是HttpSecurity类,其主要方法如表1所示。
表1 HttpSecurity类的主要方法及说明
方法 | 描述 |
---|---|
authorizeRequests() | 开启基于HttpServletRequest请求访问的限制 |
formLogin() | 开启基于表单的用户登录 |
httpBasic() | 开启基于HTTP请求的Basic认证登录 |
logout() | 开启退出登录的支持 |
sessionManagement() | 开启Session管理配置 |
rememberMe() | 开启记住我功能 |
csrf() | 配置CSRF跨站请求伪造防护功能 |
此处重点讲解用户访问控制,这里先对authorizeRequests()方法的返回值进一步查看,其中涉及到用户访问控制的主要方法及说明如表2所示。
表2 用户请求控制相关的主要方法及说明
方法 | 描述 |
---|---|
antMatchers(java.lang.String... antPatterns) | 开启Ant风格的路径匹配 |
mvcMatchers(java.lang.String... patterns) | 开启MVC风格的路径匹配(与Ant风格类似) |
regexMatchers(java.lang.String... regexPatterns) | 开启正则表达式的路径匹配 |
and() | 功能连接符 |
anyRequest() | 匹配任何请求 |
rememberMe() | 开启记住我功能 |
access(String attribute) | 使用基于SpEL表达式的角色现象匹配 |
hasAnyRole(String... roles) | 匹配用户是否有参数中的任意角色 |
hasRole(String role) | 匹配用户是否有某一个角色 |
hasAnyAuthority(String... authorities) | 匹配用户是否有参数中的任意权限 |
hasAuthority(String authority) | 匹配用户是否有某一个权限 |
authenticated() | 匹配已经登录认证的用户 |
fullyAuthenticated() | 匹配完整登录认证的用户(非rememberMe登录用户) |
hasIpAddress(String ipaddressExpression) | 匹配某IP地址的访问请求 |
permitAll() | 无条件对请求进行放行 |
表2列举了用户请求访问中涉及到的主要方法及说明,关于更多的方法读者可以自行查询API文档。另外,表中涉及到了用户的角色Role和权限Authority,在自定义用户访问控制时,通过角色Role相关的方法和通过权限Authority相关的方法都可以进行定义用户访问控制。
使用Security的官方API查询用户访问控制的相关方法后,下面在之前自定义用户认证的案例基础上,配置用户访问控制,展示Security授权管理的具体使用和效果。
1.自定义用户访问控制
打开之前创建的MVC Security自定义配置类SecurityConfig,继续重写configure(HttpSecurity http)方法进行用户访问控制,示例代码如下。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/detail/common/**").hasRole("common")
.antMatchers("/detail/vip/**").hasRole("vip")
.anyRequest().authenticated()
.and()
.formLogin();
}
在重写的configure(HttpSecurity http)方法中,自定义了用户访问权限控制。其中,对“/”路径的请求直接放行;对于以“/detail/common”开头的请求,要求用户必须为common角色(即ROLE_common权限);对于以“/detail/vip”开头的请求,要求用户必须为vip角色(即ROLE_vip权限);其他一些未映射的请求则用户必须登录认证;最后通过formLogin()方法配置了Security默认的登录页面。
2.效果测试
重启chapter07项目进行效果测试,项目启动成功后,通过浏览器访问“http://localhost:8080/
”项目首页,效果如图1所示。
图1 项目首页访问效果
从图1可以看出,直接访问“http://localhost:8080/
”可以进入项目首页,这是因为自定义的用户访问控制中,对“/”的请求是直接放行的,说明自定义用户访问控制生效。
在项目首页单击普通电影或者VIP专享电影名称查询电影详情,效果如图2所示。
图2 访问影片详情效果
从图2可以看出,在项目首页访问影片详情(实质是请求URL跳转,例如“/detail/common/1”),会直接被自定义的访问控制拦截并跳转到默认用户登录界面。接着,在此登录界面输入正确的用户名和密码信息后(如果访问的是普通电影,可以输入用户名shitou,密码123456),效果如图3所示。
图3 访问影片详情效果
在拦截的登录界面输入正确的用户名和密码后,会立即跳转到之前将要访问的影片详情页面,说明当前登录的用户shitou是有查看普通电影详情的权限。
如果单击图3左上角的“返回”链接,会再次回到项目首页。此时,之前登录的普通用户shitou还处于登录状态,再次单击VIP专享电影名称查看影片详情,效果如图4所示。
图4 普通用户访问VIP电影效果
从图4可以看出,登录后的普通用户shitou,在查看VIP电影详情时,页面会出现403 Forbidden(禁止访问)的错误信息,而控制台不会报错。上述演示结果,说明了示例中配置的用户访问控制对不同的请求拦截也生效了。另外,当前示例没有配置完善的用户注销功能,所以登录一个用户后要切换其他用户的话可以将浏览器重启,再次使用新账号登录即可。