赞
踩
我们开发一个系统,必然面临权限控制的问题,不同的用户具有不同的访问、操作、数据权限。形成理论的权限控制模型有:自主访问控制(DAC: Discretionary Access Control)、强制访问控制(MAC: Mandatory Access Control)、基于属性的权限验证(ABAC: Attribute-Based Access
Control)等。最常被开发者使用也是相对易用、通用的就是RBAC权限模型(Role-Based Access
Control)
RBAC权限模型(Role-Based Access Control)即:基于角色的权限控制。模型中有几个关键的术语:
RBAC权限模型核心授权逻辑如下:
想到权限控制,人们最先想到的一定是用户与权限直接关联的模式,简单地说就是:某个用户具有某些权限。如图:
这种模型能够清晰的表达用户与权限之间的关系,足够简单。但同时也存在问题:
这样只需要维护角色和权限之间的关系就可以了. 如果业务员的权限发生变更, 只需要变动业务员角色和权限之前的关系进行维护就可以了. 用户和权限就分离开来了. 如下图
- import com.baomidou.mybatisplus.core.mapper.BaseMapper;
- import com.lagou.domain.Permission;
- import org.apache.ibatis.annotations.Select;
-
- import java.util.List;
-
-
- public interface PermissionMapper extends BaseMapper<Permission> {
- /**
- * 根据用户ID查询权限
- *
- * @param id
- * @return
- */
- @Select("SELECT p.* FROM t_permission p,t_role_permission rp,t_role r,t_user_role ur,t_user u " +
- "WHERE p.id = rp.PID AND rp.RID = r.id AND r.id = ur.RID AND ur.UID = u.id AND u.id =#{id}")
- List<Permission> findByUserId(Integer id);
- }

这个是在实现UserDetailsService接口,在重写的loadUserByUsername的方法中
- Collection<GrantedAuthority> authorities = new ArrayList<>(); // 权限的集合,先声明一个权限集合, 因为构造方法里面不能传入null
- // 基于数据库查询用户对应的权限
- List<Permission> permissionList = permissionService.findByUserId(user.getId());
- for (Permission permission : permissionList) {
- // 授权
- authorities.add(new SimpleGrantedAuthority(permission.getPermissionTag()));
- }
这个是在我们自定义类SecurityConfig继承了WebSecurityConfigurerAdapter接口,在其重写方法中设置,void configure(HttpSecurity http)
- // 查询数据库所有权限列表
- List<Permission> list = permissionService.list();
- for (Permission permission : list) {
- http.authorizeRequests().antMatchers(permission.getPermissionUrl())
- // 添加请求权限
- .hasAuthority(permission.getPermissionTag());
- }
之所以使用hasAuthority而不是使用hasRole是因为hasRole会在权限的前面加上"ROLE_".
在jsp页面或者thymeleaf模板页面中我们可以使用spring security提供的权限标签来进行权限控制.要想使用thymeleaf为SpringSecurity提供的标签属性,首先需要引入thymeleaf-extras-springsecurity依赖支持。
- <!--添加thymeleaf为SpringSecurity提供的标签依赖 -->
- <dependency>
- <groupId>org.thymeleaf.extras</groupId>
- <artifactId>thymeleaf-extras-springsecurity5</artifactId>
- <version>3.0.4.RELEASE</version>
- </dependency>
- <!DOCTYPE html>
- <html xmlns:th="http://www.thymeleaf.org"
- xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
判断用户是否已经登陆认证,引号内的参数必须是isAuthenticated()。
sec:authorize="isAuthenticated()"获得当前用户的用户名,引号内的参数必须是name。
sec:authentication=“name”
判断当前用户是否拥有指定的权限。引号内的参数为权限的名称。
sec:authorize=“hasRole(‘role’)”
- <div class="leftnav">
- <div class="leftnav-title">
- <div sec:authorize="isAuthenticated()"> <!--有权限时,为true,则会显示-->
- <span sec:authentication="name"></span>
- <img src="images/y.jpg" class="radius-circle rotate-hover" height="50" alt=""/>
- </div>
- </div>
- <div sec:authorize="hasAuthority('user:findAll')"> <!--有权限时,为true,则会显示-->
- <h2><span class="icon-user"></span>系统管理</h2>
- <ul style="display:block">
- <li><a href="/user/findAll" target="right"><span class="icon-caretright"></span>用户管理</a></li>
- <li><a href="javascript:void(0)" onclick="toCors()" target="right">
- <span class="icon-caret-right"></span>跨域测试</a></li>
- </ul>
- </div>
- <div sec:authorize="hasAuthority('product:findAll')"> <!--有权限时,为true,则会显示-->
- <h2><span class="icon-pencil-square-o"></span>数据管理</h2>
- <ul>
- <li><a href="/product/findAll" target="right"><span class="iconcaret-right"></span>商品管理</a></li>
- </ul>
- </div>
- </div>

当我们开启CSRF防护后,我们点击项目中的登录按钮,会报404错误,这是因为logout登出功能的方法必须为post请求,并且我们还要携带
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>这里面的参数。这样才能登出成功,而不会报错。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。