基本概念
Spring中提供安全认证服务的框架,认证:验证用户密码是否正确的过程,授权:对用户能访问的资源进行控制
用户登录系统时我们协助 SpringSecurity 把用户对应的角色、权限组装好,同时把各个资源所要求的权限信息设定好,剩下的“登录验证”、“权限验证”等等工作都交给SpringSecurity。
权限管理过程中的相关概念
主体
英文单词:principal
使用系统的用户或设备或从其他系统远程登录的用户等等。简单说就是谁使用系统谁就是主体。
认证
英文单词:authentication
权限管理系统确认一个主体的身份,允许主体进入系统。简单说就是“主体”证明自己是谁。笼统的认为就是以前所做的登录操作。
授权
英文单词:authorization
将操作系统的“权力”“授予”“主体”,这样主体就具备了操作系统中特定功能的能力。
所以简单来说,授权就是给用户分配权限。
使用
pom文件中加入spring security的依赖
<!-- SpringSecurity 对 Web 应用进行权限管理 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.2.10.RELEASE</version>
</dependency>
<!-- SpringSecurity 配置 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.2.10.RELEASE</version>
</dependency>
<!-- SpringSecurity 标签库 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>4.2.10.RELEASE</version>
</dependency>
web.xml加入SpringSecurity控制权限的Filte
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>
@PreAuthorize("hasAuthority('role:get') or hasAnyRole('经理')")// 需要有role:get权限才可以访问
@ResponseBody
@GetMapping("/role/get/page/info.json")
public ResultEntity<PageInfo<Role>> getPageInfo(
@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize", defaultValue = "4") Integer pageSize,
@RequestParam(value = "keyword", defaultValue = "") String keyword
) {
// 获取页面数据
PageInfo<Role> pageInfo = roleService.getRoleByKeyword(pageNum, pageSize, keyword);
// 如果出现异常,dispatcherServlet会进行处理
return ResultEntity.successWithData(pageInfo);
}
@PostAuthorize
先执行方法然后根据方法返回值判断是否具备权限。
例如:查询一个 Admin 对象,在@PostAuthorize 注解中和当前登录的 Admin 对象进行比较,如果不一致,则判断为不能访问。实现“只能查自己”效果。
@PostAuthorize("returnObject.data.loginAcct == principal.username")
使用 returnObject 获取到方法返回值,使用 principal 获取到当前登录用户的主体对象。
通过故意写错表达式,然后从异常信息中发现表达式访问的是下面这个类的属性:
org.springframework.security.access.expression.method.MethodSecurityExpressionRoot
@PreFilter
在方法执行前对传入的参数进行过滤。只能对集合类型的数据进行过滤。
@PreFilter(value="filterObject%2==0")
@ResponseBody
@RequestMapping("/admin/test/pre/filter")
public ResultEntity<List<Integer>> saveList(@RequestBody List<Integer> valueList) {
return ResultEntity.successWithData(valueList);
}
@PostFilter
在方法执行后对方法返回值进行过滤。只能对集合类型的数据进行过滤。
CrowdUserDetailsService
其实返回的就是SpringSecurity的User对象,只是做了一层封装。
package com.atguigu.crowd.mvc.config;
import com.atguigu.crowd.entity.Admin;
import com.atguigu.crowd.entity.Role;
import com.atguigu.crowd.service.api.AdminService;
import com.atguigu.crowd.service.api.AuthService;
import com.atguigu.crowd.service.api.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class CrowdUserDetailsService implements UserDetailsService {
@Autowired
private AdminService adminService;
@Autowired
private RoleService roleService;
@Autowired
private AuthService authService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 1、根据账号名称查找Admin对象
Admin admin = adminService.getAdminByLoginAcct(username);
// 2、获取adminId
Integer adminId = admin.getId();
// 3、根据adminId查询角色信息
List<Role> roles = roleService.getAssignedRole(adminId);
// 4、根据adminId查询权限名字信息
List<String> auths = authService.getAssignedAuthNameByAdminId(adminId);
// 5、创建集合对象来存储GrantedAuthority
ArrayList<GrantedAuthority> authorities = new ArrayList<>();
// 6、遍历存入角色消息
for (int i = 0; i < roles.size(); i++) {
// 需要加前缀,因为SpringSecurity就是通过ROLE_来区分是角色还是权限
String roleName = "ROLE_" + roles.get(i).getName();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(roleName);
authorities.add(authority);
}
// 7、遍历存入权限信息
for (int i = 0; i < auths.size(); i++) {
String authName = auths.get(i);
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(authName);
authorities.add(authority);
}
// 8、封装到SecurityAdmin对象中,它继承了SpringSecurity的User类
SecurityAdmin securityAdmin = new SecurityAdmin(admin, authorities);
return securityAdmin;
}
}
BCryptPasswordEncoder
它是SpringSecurity自带的密码加密与验证的类。
页面元素控制
取出当前登录对象
<%--需要导入taglib--%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>
<%--principal 是我们自己封装的 SecurityAdmin 对象(返回的SpringSecurity的User对象)--%>
<security:authentication property="principal.originalAdmin.userName"/>
标签库控制
<%--需要导入taglib--%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>
<security:authorize access="hasRole('经理')">
<!-- 开始和结束标签之间是要进行权限控制的部分。检测当前用户是否有权限,有权限
就显示这里的内容,没有权限就不显示。 --> ……
</security:authorize>
access属性可以传入权限控制相关的表达式。
/>
### 标签库控制
```html
<%--需要导入taglib--%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %>
<security:authorize access="hasRole('经理')">
<!-- 开始和结束标签之间是要进行权限控制的部分。检测当前用户是否有权限,有权限
就显示这里的内容,没有权限就不显示。 --> ……
</security:authorize>
access属性可以传入权限控制相关的表达式。
到此这篇关于SpringSecurity概念以及整合ssm框架的文章就介绍到这了,更多相关SpringSecurity整合ssm框架内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!