Spring Security快速入门(四) 访问控制

一、访问控制url匹配

在前面讲解了认证中所有常用配置,主要是对`http.formLogin()`进行操作。而在配置类中`http.authorizeRequests()`主要是对url进行控制,也就是我们所说的授权(访问控制)。

http.authorizeRequests()也支持连缀写法,总体公式为:

  • url 匹配规则.权限控制方法

通过上面的公式可以有很多 url 匹配规则和很多权限控制方法。
这些内容进行各种组合就形成了Spring Security中的授权。

在所有匹配规则中取所有规则的交集。配置顺序影响了之后授权效果,越是具体的应该放在前面,越
是笼统的应该放到后面。

1. anyRequest()

在之前认证过程中我们就已经使用过 anyRequest(),表示匹配所有的请求。一般情况下此方法都会
使用,设置全部内容都需要进行认证

// 表示所有请求,都必须经过登录认证后才能被访问。
http.anyRequest().authenticated();

2. antMatchers()

在这里插入图片描述
antMatchers()有三个重载方式,可以指定Http请求方法,也可以指定ant表达式,用于匹配URL规则。

规则如下:

  • ? :匹配一个字符
  • *: 匹配 0 个或多个字符
  • ** :匹配 0 个或多个目录

在实际项目中经常需要放行所有静态资源,下面演示放行 js 文件夹下所有脚本文件。

http.antMatchers("/js/**", "/css/**").permitAll();

还有一种配置方式是只要是.js 文件都放行。

http.antMatchers("/**/*.js").permitAll();

3. regexMatchers()

使用正则表达式进行匹配。和 antMatchers() 主要的区别就是参数, antMatchers() 参数是 ant表达式,
regexMatchers() 参数是正则表达式。

演示所有以.js 结尾的文件都被放行。

http.regexMatchers(". + [.]js").permitAll();

无论是antMatchers() 还是regexMatchers() 都具有两个参数的方法,
其中第一个参数都是HttpMethod ,表示请求方式,
当设置了HttpMethod 后表示只有设定的特定的请求方式才执行对应的权限设置。

4. mvcMatchers()

mvcMatchers()适用于配置了 servletPath 的情况。

servletPath 就是所有的 URL 的统一前缀。在 SpringBoot 整合SpringMVC 的项目中可以在
application.properties 中添加下面内容设置 servletPath

spring.mvc.servlet.path=/xxxx

在 Spring Security 的配置类中配置.servletPath() 是 mvcMatchers()返回值特有的方法,
antMatchers()和 regexMatchers()没有这个方法。在servletPath() 中配置了servletPath 后,
mvcMatchers()直接写 SpringMVC 中@RequestMapping()中设置的路径即可。

http.mvcMatchers("/demo").servletPath("/xxxx").permitAll();

如果不习惯使用 mvcMatchers()也可以使用 antMatchers(),下面代码和上面代码是等效:

http.antMatchers("/xxxx/demo").permitAll();

二、访问控制方法

在匹配到URL之后,我们就需要对这些URL进行控制,那些是可以直接放行的,哪些是需要认证之后才能访问的,哪些是需要特定权限的等等。

1. 内置访问控制方法

  • permitAll():表示所匹配的 URL 任何人都允许访问。
  • authenticated():表示所匹配的URL都需要被认证才能访问。
  • anonymous()表示只允许匿名用户访问,已登录用户不能访问。
  • denyAll():表示所匹配的 URL 都不允许被访问。
  • rememberMe():被remember me的用户允许访问。
  • fullyAuthenticated():如果用户不是被 remember me 的,才可以访问。

2. 基于角色权限判断

除了上面的内置权限控制。Spring Security 中还支持很多其他权限控制。这些方法一般都用于用户已经被认证后,
判断用户是否具有特定的要求。

①:hasAuthority(String)

判断用户是否具有特定的权限,用户的权限是在自定义登录逻辑中loadUserByUsername()创建 User 对象时指定的。一般是从数据库中查询出来的权限。

下图中admin和normal 就是用户的权限。admin和normal 严格区分大小写。

在这里插入图片描述
在配置类中通过 hasAuthority(“admin”)设置具有 admin 权限时才能访问。

http.antMatchers("/index.html").hasAuthority("admin")

②:hasAnyAuthority(String …)

如果用户具备给定权限中某一个,就允许访问。

下面代码中由于大小写和用户的权限不相同,所以用户无权访问

http.antMatchers("/index.html").hasAnyAuthority("adMin","admiN")

③:hasRole(String)

如果用户具备给定角色就允许访问。否则出现 403。

参数取值同样来源于自定义登录逻辑 UserDetailsService 实现类中返回的 User 对象中给 User 赋予的授
权。

在给用户赋予角色时角色需要以: ROLE_开头,后面添加角色名称。例如:ROLE_abc 其中 abc 是角
色名,ROLE_是固定的字符开头。同样,角色也是保存在数据库中的。

注意:使用 hasRole()时参数只写 abc 即可。否则启动报错。

在这里插入图片描述

在配置类中直接写 abc 即可。

在这里插入图片描述

④:hasAnyRole(String …)

如果用户具备给定角色的任意一个,就允许被访问

⑤:hasIpAddress(String)

如果请求是指定的 IP 就运行访问。

可以通过 request.getRemoteAddr() 获取 ip 地址。

3. 基于表达式的访问控制

1. 内置访问控制方法2. 基于角色权限判断中,实际上底层实现都是调用access(表达式)这样的一个方式。

可以通过access() 实现和之前学习的权限控制完成相同的功能。

以 hasRole 和 和 permitAll 举例:
在这里插入图片描述

我们可以使用自定义方法。

实现一个判断登录用户是否具有访问当前 URL 权限。

新建一个接口和它的实现类,实现判断。

接口如下:

package com.linqibin.springsecuritystudy.service;

import org.springframework.security.core.Authentication;

import javax.servlet.http.HttpServletRequest;

public interface MyAccessService {

    boolean hasUriPermission(HttpServletRequest request, Authentication authentication);
}

实现类:

package com.linqibin.springsecuritystudy.service.impl;

import com.linqibin.springsecuritystudy.service.MyAccessService;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;

@Service
public class MyAccessServiceImpl implements MyAccessService {
    @Override
    public boolean hasUriPermission(HttpServletRequest request, Authentication authentication) {
        Object obj = authentication.getPrincipal();
        if (obj instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) obj;
            Collection<? extends GrantedAuthority> authorities =
                    userDetails.getAuthorities();
            return authorities.contains(new
                    SimpleGrantedAuthority(request.getRequestURI()));
        }
        return false;
    }
}

修改配置类,在 access 中通过@bean的id名.方法(参数)的形式进行调用配置类中修改如下:

在这里插入图片描述
接下来,我们去修改一下UserDetailServiceImpl中的授权:
在这里插入图片描述
在这里插入图片描述

4. 基于注解的访问控制

在 Spring Security 中提供了一些访问控制的注解。这些注解都是默认是都不可用的,需要通过
@EnableGlobalMethodSecurity 进行开启后使用。

如果设置的条件允许,程序正常执行。如果不允许会报 500。
在这里插入图片描述

这些注解可以写到 Service 接口或方法上,也可以写到 Controller或 Controller 的方法上。通常情况下
都是写在控制器方法上的,控制接口URL是否允许被访问。

①:@Secured

@Secured 是专门用于判断是否具有角色的。能写在方法或类上。**注意:参数要以 ROLE_开头。**此处与基于权限判断的方式不同。

在 启 动 类 ( 也 可 以 在 配 置 类 等 能 够 扫 描 的 类 上 ) 上 添 加@EnableGlobalMethodSecurity(securedEnabled = true)

在这里插入图片描述
在控制器方法上添加@Secured 注解

在这里插入图片描述
这样,想要访问这个方法,认证过后的用户就必须用友abc角色。

②:@PreAuthorize/@PostAuthorize

@PreAuthorize 和@PostAuthorize 都是方法或类级别注解。

  • @PreAuthorize 表示访问方法或类在执行之前先判断权限,大多情况下都是使用这个注解,注解
    的参数和access()方法参数取值相同,都是权限表达式。
  • @PostAuthorize 表示方法或类执行结束后判断权限,此注解很少被使用到。

第一步要做的也是开启注解。
在这里插入图片描述

第二步添加注解。
在控制器方法上添加@PreAuthorize,参数可以是任何 access()支持的表达式。
在这里插入图片描述
如果不满足条件,会报以下错误:

在这里插入图片描述

三、总结

本篇文章我们先了解了如何去通过一些表达式匹配到请求的url,之后再通过一系列的访问控制方法,来判断哪些请求是允许的,哪些是不允许的。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值