SpringBoot整合SpringSecurity系列(8)-角色权限控制

1,602 阅读4分钟

一、角色权限判断

  1. 除了内置权限控制外,Spring Security 中还支持很多其他权限控制,这些方法一般都用于用户已经被认证后,判断用户是否具有特定的权限
  2. 例如登录微信之后,是否有权限发红包、发朋友圈等,后面的操作是建立在登录验证之后,表示授权部分,前者为认证部分
  3. 内置主要有以下五个角色权限验证方法
public class AuthorizedUrl {
	/**
	 * Shortcut for specifying URLs require a particular role. If you do not want to
	 * have "ROLE_" automatically inserted see {@link #hasAuthority(String)}.
	 * @param role the role to require (i.e. USER, ADMIN, etc). Note, it should not
	 * start with "ROLE_" as this is automatically inserted.
	 * @return the {@link ExpressionUrlAuthorizationConfigurer} for further
	 * customization
	 */
	public ExpressionInterceptUrlRegistry hasRole(String role) {
		return access(ExpressionUrlAuthorizationConfigurer.hasRole(role));
	}

	/**
	 * Shortcut for specifying URLs require any of a number of roles. If you do not
	 * want to have "ROLE_" automatically inserted see
	 * {@link #hasAnyAuthority(String...)}
	 * @param roles the roles to require (i.e. USER, ADMIN, etc). Note, it should not
	 * start with "ROLE_" as this is automatically inserted.
	 * @return the {@link ExpressionUrlAuthorizationConfigurer} for further
	 * customization
	 */
	public ExpressionInterceptUrlRegistry hasAnyRole(String... roles) {
		return access(ExpressionUrlAuthorizationConfigurer.hasAnyRole(roles));
	}

	/**
	 * Specify that URLs require a particular authority.
	 * @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
	 * @return the {@link ExpressionUrlAuthorizationConfigurer} for further
	 * customization
	 */
	public ExpressionInterceptUrlRegistry hasAuthority(String authority) {
		return access(ExpressionUrlAuthorizationConfigurer.hasAuthority(authority));
	}

	/**
	 * Specify that URLs requires any of a number authorities.
	 * @param authorities the requests require at least one of the authorities (i.e.
	 * "ROLE_USER","ROLE_ADMIN" would mean either "ROLE_USER" or "ROLE_ADMIN" is
	 * required).
	 * @return the {@link ExpressionUrlAuthorizationConfigurer} for further
	 * customization
	 */
	public ExpressionInterceptUrlRegistry hasAnyAuthority(String... authorities) {
		return access(ExpressionUrlAuthorizationConfigurer.hasAnyAuthority(authorities));
	}

	/**
	 * Specify that URLs requires a specific IP Address or <a href=
	 * "https://forum.spring.io/showthread.php?102783-How-to-use-hasIpAddress&p=343971#post343971"
	 * >subnet</a>.
	 * @param ipaddressExpression the ipaddress (i.e. 192.168.1.79) or local subnet
	 * (i.e. 192.168.0/24)
	 * @return the {@link ExpressionUrlAuthorizationConfigurer} for further
	 * customization
	 */
	public ExpressionInterceptUrlRegistry hasIpAddress(String ipaddressExpression) {
		return access(ExpressionUrlAuthorizationConfigurer.hasIpAddress(ipaddressExpression));
	}
}

二、内置权限判断

2.1 hasAuthority(String)

  1. 判断用户是否具有特定的权限,用户的权限在登录逻辑中(UserDetailsService实现类)返回UserDetails对象时指定,也可以是数据库验证方式中在数据库配置的权限
  2. 如之前创建的用户权限信息(user_role)中的下面信息就表示所具备的权限
    • ROLE_ADMIN和ROLE_USER就是用户的权限,权限严格区分大小写

在这里插入图片描述 3. 在配置类中通过 hasAuthority("ROLE_ADMIN") 设置表示具有管理员权限时才能访问

resources/static/ 创建只有ROLE_ADMIN权限(root用户)才能访问的root.html

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>SpringBoot Security</title>
</head>
<body>
  <h3>欢迎登录SpringBoot Security管理员首页</h3>
</body>
</html>
.antMatchers("/admin.html").hasAuthority("ROLE_ADMIN")
  1. 注意hasAuthority只能指定一个权限

ExpressionInterceptUrlRegistry hasAuthority(String authority)

  1. 使用admin账号登录(root才有ROLE_ADMIN权限),提示403禁止访问

在这里插入图片描述

  1. 使用root账号登录,正常访问

在这里插入图片描述 7. 权限正常控制,特别注意权限区分大小写

ROLE_ADMIN和role_admin是两个权限

2.2 hasAnyAuthority(String ...)

  1. 如果用户具备给定权限中某一个,就允许访问
  2. resources/static/ 创建具备ROLE_USER和ROLE_ADMIN权限(root和admin用户)能访问的admin.html
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>SpringBoot Security</title>
</head>
<body>
  <h3>欢迎登录SpringBoot Security Admin首页</h3>
</body>
</html>
  1. 配置文件中配置权限访问
.antMatchers("/admin.html").hasAnyAuthority("ROLE_ADMIN", "ROLE_USER")
  1. 此时使用root或admin用户均可以正常访问

2.3 hasRole(String)

  1. 判断用户是否具备指定角色,如果用户具备给定角色就允许访问,否则出现 403
  2. 参数取值来源于自定义登录逻辑UserDetailsService实现类中创建返回User对象时给User赋予的授权
  3. 在给用户赋予角色时角色需要以 ROLE_ 开头,后面添加角色名称
    • ROLE_ADMINROLE_ 是固定开头,ADMIN 是角色名称
    • 特别注意和hasAnyAuthority、hasAuthority的区别,后者必须要全称,前者只要 ROLE_角色
  4. 使用 hasRole()时参数只需要写 ADMIN、USER 即可,如果带前缀启动报错
.antMatchers("/root.html").hasRole("ADMIN")
  1. 带上ROLE_启动报错
role should not start with 'ROLE_' since it is automatically inserted. Got 'ROLE_ADMIN'
  1. 这是由于源码里面默认会拼接 ROLE_,并且断言了不能以其开头
    • org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer

在这里插入图片描述

2.4 hasAnyRole(String ...)

  1. 如果用户具备给定角色的任意一个,就允许被访问
  2. 和之前hasAnyAuthority(String ...)类似,只需要替换为hasAnyRole规则即可
.antMatchers("/admin.html").hasAnyRole("ADMIN", "USER")
  1. 使用 hasRole()时参数也只需要写 ADMIN、USER 即可
    • org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer

在这里插入图片描述

2.5 hasIpAddress(String)

  1. 如果请求ip是指定的ip发起则允许访问,可以通过 request.getRemoteAddr() 获取ip地址
  2. 需要注意在本机进行测试时 localhost 和 127.0.0.1 输出的 ip地址是不一样的
    • 通过 localhost 进行访问时IP地址:0:0:0:0:0:0:0:1
    • 通过 127.0.0.1 访问时IP地址:127.0.0.1
    • 通过具体 ip 进行访问时IP地址:具体IP地址
  3. resources/static/ 创建只有ip是127.0.0.1时允许访问的ip.html
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>SpringBoot Security</title>
</head>
<body>
  <h3>IP验证成功,SpringBoot Security Admin首页</h3>
</body>
</html>
.antMatchers("/ip.html").hasIpAddress("127.0.0.1")
  1. 通过正常IP地址访问

在这里插入图片描述

  1. 通过localhost访问

在这里插入图片描述