SpringBoot整合SpringSecurity系列(1

一、Thymeleaf-Security

  1. Spring Security 可以在一些视图技术中进行控制显示效果,如JSP 或 Thymeleaf
  2. 在非前后端分离且使用 Spring Boot 的项目中大多使用 Thymeleaf 作为视图展示技术
  3. Thymeleaf 对 Spring Security 的支持都放在hymeleaf-extras-springsecurityX中,目前最新版本为 5。所以需要在项目中添加此 jar 包的依赖和 thymeleaf 的依赖
1
2
3
4
5
6
7
8
9
xml复制代码<!-- thymeleaf依赖 -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  1. 在 html 页面中引入thymeleaf命名空间和security命名空间,引用命名空间之后才能使用对应属性信息
1
2
3
4
5
html复制代码<!DOCTYPE html>
<html lang="zh"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
</html>
  1. 配置文件中配置thymeleaf相关属性,默认属性参考类
    • org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties
1
2
3
4
5
6
7
8
9
10
11
12
13
yaml复制代码spring:
# Thymeleaf
thymeleaf:
# 关闭缓存
cache: false
# 开启引擎
enabled: true
# 视图模型
mode: HTML
# 指定后缀
suffix: .html
# 模板路径
prefix: classpath:/templates/

二、Thymeleaf获取属性

2.1 获取属性

  1. 可以在html页面中通过 sec:authentication=”” 获取 UsernamePasswordAuthenticationToken 中以及父类中的属性
    • org.springframework.security.authentication.UsernamePasswordAuthenticationToken

image.png
2. 源码属性如下

  • name :登录账号名称
  • principal:登录主体,在自定义登录逻辑中是 UserDetails
  • credentials:凭证信息
  • authorities:权限和角色
  • details:WebAuthenticationDetails实例,可以获取 remoteAddress (客户端ip)和 sessionId (当前 sessionId)

image.png
3. 在 /templates/ 新建 security.html 用于显示上述所述属性信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
html复制代码<!DOCTYPE html>
<html lang="zh"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title>权限信息</title>
</head>
<body>
<ol>
<!-- 属性获取,authentication:n. 证明;鉴定;证实 -->
<li>登录账号:<span sec:authentication="name"></span></li>
<!-- principal相当于UserDetails信息 -->
<li>登录账号:<span sec:authentication="principal.username"></span></li>
<li>登录密码:<span sec:authentication="principal.password"></span></li>
<li>账号过期:<span sec:authentication="principal.accountNonExpired"></span></li>
<li>账号锁定:<span sec:authentication="principal.accountNonLocked"></span></li>
<li>凭证过期:<span sec:authentication="principal.credentialsNonExpired"></span></li>
<li>账号启用:<span sec:authentication="principal.enabled"></span></li>
<li>凭证:<span sec:authentication="credentials"></span></li>
<li>权限和角色:<span sec:authentication="authorities"></span></li>
<!-- WebAuthenticationDetails实例 -->
<li>客户端地址:<span sec:authentication="details.remoteAddress"></span></li>
<li>sessionId:<span sec:authentication="details.sessionId"></span></li>
</ol>
</body>
</html>
  1. 在控制器中添加转发路径,必须要通过转化,直接访问无法获取属性
1
2
3
4
java复制代码@RequestMapping("/security")
public String security() {
return "security";
}
  1. 正常访问项目,可以显示如下权限信息
1
2
3
4
5
6
7
8
9
10
11
ruby复制代码登录账号:admin
登录账号:admin
登录密码:$2a$10$.9UpYAxTDg/cd8U7wtal5et7TcC7QaInySM1p8tBEp.OO20UvjR/S
账号过期:true
账号锁定:true
凭证过期:true
账号启用:true
凭证:
权限和角色:[{"authority":"ROLE_USER","id":3,"userId":2}]
客户端地址:0:0:0:0:0:0:0:1
sessionId:CAD8A5A28BC2EBDDF0990111BC86C3CA

2.2 权限判断

  1. 可以在html页面中通过 sec:authorize=”” 进行鉴权,用来控制是否对应用户具备对应菜单
  2. 在security.html中增加权限相关信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
html复制代码<!DOCTYPE html>
<html lang="zh"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title>权限信息</title>
</head>
<body>
<ol>
<!-- 属性获取,authentication:n. 证明;鉴定;证实 -->
<li>登录账号:<span sec:authentication="name"></span></li>
<!-- principal相当于UserDetails信息 -->
<li>登录账号:<span sec:authentication="principal.username"></span></li>
<li>登录密码:<span sec:authentication="principal.password"></span></li>
<li>账号过期:<span sec:authentication="principal.accountNonExpired"></span></li>
<li>账号锁定:<span sec:authentication="principal.accountNonLocked"></span></li>
<li>凭证过期:<span sec:authentication="principal.credentialsNonExpired"></span></li>
<li>账号启用:<span sec:authentication="principal.enabled"></span></li>
<li>凭证:<span sec:authentication="credentials"></span></li>
<li>权限和角色:<span sec:authentication="authorities"></span></li>
<!-- WebAuthenticationDetails实例 -->
<li>客户端地址:<span sec:authentication="details.remoteAddress"></span></li>
<li>sessionId:<span sec:authentication="details.sessionId"></span></li>
</ol>

<div>
<!-- 权限判断,authorize:vt. 批准,认可;授权给;委托代替 -->
通过权限判断:
<button sec:authorize="hasAuthority('ROLE_ADMIN')">新增</button>
<button sec:authorize="hasAuthority('ROLE_ADMIN')">删除</button>
<button sec:authorize="hasAuthority('ROLE_ADMIN')">修改</button>
<button sec:authorize="hasAnyAuthority('ROLE_ADMIN', 'ROLE_USER')">查看</button>
<br/>
通过角色判断:
<button sec:authorize="hasRole('ADMIN')">新增</button>
<button sec:authorize="hasRole('ADMIN')">删除</button>
<button sec:authorize="hasRole('ADMIN')">修改</button>
<button sec:authorize="hasAnyRole('ADMIN', 'USER')">查看</button>
</div>
</body>
</html>
  1. access() 中表达式使用一致,分别使用admin和root用户登录,可以看到菜单部分对于没有权限的菜单并不会显示

image.png
4. 对于非前后分离的项目来说,菜单权限控制比较简单;对于前后分离的菜单不能直接使用到thymeleaf中对于security的支持,需要自定处理权限管理

三、thymeleaf解决csrf

  1. /templates/ 中新增 login.html,添加隐藏域name值为 _csrf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
html复制代码<!DOCTYPE html>
<html lang="zh"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title>系统登录</title>
</head>
<body>
<form action="/login" method="post">
用户名:<input type="text" name="username" value="admin" /><br/>
密码:<input type="password" name="password" value="tianxin" /><br/>
<input type="hidden" th:value="${_csrf.token}" name="_csrf" th:if="${_csrf}"/>
记住我:<input type="checkbox" name="remember-me" value="true" /><br/>
<input type="submit" value="登录"/>
</form>
</body>
</html>
  1. 添加在controller中添加转化请求
1
2
3
4
java复制代码@RequestMapping("/csrfLogin")
public String csrfLogin() {
return "login";
}
  1. 在登录控制中需要放行 /csrfLogin 路径的访问
1
2
3
java复制代码http.authorizeRequests()
// csrf登录放行
.antMatchers("/csrfLogin").permitAll();
  1. 安全配置类中注释掉csrf相关代码
1
2
java复制代码// 关闭csrf保护
// http.csrf().disable();
  1. 使用csrfLogin访问登录页面,正常输入账号和密码之后系统正常登录

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%