- 一、部分方法介绍
- 二、流程
- 三、代码
- 四、参考文献
Spring Security 是 Spring 项目组中用来提供安全认证服务的框架。
网上相关的教程很多,也很详细。如:spring security——基本介绍(一)
这里就不过多赘述了,只写部分方法的使用及其注意点。
注:在 Security 中 方法大多为链式调用,且返回类型类名较长,故本篇文章将全程省略返回类型
一、部分方法介绍
配置类 SecurityConfig
1.1 注解、继承、重写的方法等
1.1.1 @EnableWebSecurity 注解
功能:表示该类启用了 Spring Security 的 Web 安全支持
1.1.2 configure(HttpSecurity http) 继承
功能:
SecurityConfig类最基础的方法,定义了
- 请求授权的规则
- 表单验证__登录页的配置
- 注销、记住我等功能的配置
1.1.3 configure(AuthenticationManagerBuilder auth) 继承
功能:构建一个基于内存的身份验证器
注:
- 该方法将身份信息存储在内存中
在 configure(HttpSecurity http) 中使用以下内容
1.2 请求授权的规则
1.2.1 authorizeRequests()
功能:开启通过URL授权模式
注:
- 必需的方法,写就对了
- 配合 antMatchers(String… antPatterns) 使用
1.2.2 antMatchers(String… antPatterns)
功能:指定需要授权的链接
1.2.3 permitAll()
功能:允许所有人通过调用该方法的请求
1.2.4 hasRole(String role)
功能:指定允许通过调用该方法的请求的角色
注:
- 该方法会自动向参数中的角色插入前缀 “ROLE“_
- 参数举例:USER, ADMIN
- 如果不需要前缀,可以使用 hasAuthority(String authority)
1.2.5 hasAuthority(String authority)
功能:指定允许通过调用该方法的请求的角色
注:
- 该方法与 hasRole(String role) 不同的是,它不会自动插入前缀 “ROLE“_
- 参数举例:ROLE_USER, ROLE_ADMIN
1.3 表单验证__登录页
1.3.1 formLogin()
功能:开启表单验证
注:
- 如果没有使用 loginPage(String loginPage) 指定登录页,则会生成一个默认的登录表单
1.3.2 loginPage(String loginPage)
功能:指定登录页面
注:
- 参数为 跳转到登录页面的请求
- 该方法只能出现一次
1.3.3 loginProcessingUrl(String loginProcessingUrl)
功能:指定登录页面的URL
注:
- 该方法会覆盖 loginPage(String loginPage) 中指定的 url
- 该方法可以多次出现,即指定多个 url
1.3.4 usernameParameter(String usernameParameter)
功能:执行身份验证时查找用户名的HTTP参数。默认设置是“username”
注:
- 与前端登录页填写用户名的
<input>
的name
属性一致
1.3.5 passwordParameter(String passwordParameter)
功能:执行身份验证时查找密码的HTTP参数。默认设置是“password”
注:
- 与前端登录页填写密码的
<input>
的name
属性一致
1.4 注销
1.4.1 logout()
功能:开启注销功能
1.4.2 logoutSuccessUrl(String logoutSuccessUrl)
功能:注销成功后跳转到 对应请求(参数)
1.5 记住我
1.5.1 rememberMe()
功能:开启记住我功能
1.5.2 rememberMeParameter(String rememberMeParameter)
功能:用于表示在登录时记住用户的HTTP参数
注:
- 与前端登录页记住我的
<input>
的name
属性一致
在 configure(AuthenticationManagerBuilder auth) 中使用以下内容
1.6 内存中的身份验证
1.6.1 inMemoryAuthentication()
功能:将内存中身份验证添加到 auth 中,并返回一个配置对象,以允许对内存中身份验证进行定制
1.6.2 passwordEncoder(PasswordEncoder passwordEncoder)
功能:指定加密方式
注:
- 参数为一个对象。
- 该对象必须继承接口
org.springframework.security.crypto.password.PasswordEncoder
1.6.3 withUser(String username)
功能:添加用户至内存中
1.6.4 password(String password)
功能:指定添加的用户的密码
注:
1.此项是必需的
1.6.5 roles(String… roles)
功能与注意点都与 hasRole(String role) 相同
1.6.6 authorities(String… authorities)
功能与注意点都与 hasAuthority(String authority) 相同
前端页面 Thymeaf
1.2.1 根据用户的角色动态显示不同的内容
在 div 中加入 sec:authorize="hasRole(String roleName)"
二、流程
2.1 自定义登录页方法执行流程
- 前端页面提交请求:/login
- 控制层接收请求:@RequestMapping(“/login”)
- 完成登录操作
- 进入Security配置类判断:
- 判断 loginPage(“/toLogin”) :参数不匹配 toLogin != login
- 判断 loginProcessingUrl(“/login”) :参数匹配,权限判断通过
三、代码
此处使用的是 狂神 的 Spring Security 教程中的演示代码,并以此为基础做了部分修改
依赖 pom.xml
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
...
</dependencies>
SecurityConfig.java
package nuc.ss.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
// AOP:拦截器
@EnableWebSecurity // 开启WebSecurity模式
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//链式编程
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
// 首页所有人都可以访问,功能也只有对应有权限的人才能访问到
// 请求授权的规则
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
// 没有权限默认会到登录页面,需要开启登录的页面
// /login页面
http.formLogin()
.usernameParameter("username")
.passwordParameter("password")
.loginPage("/toLogin")
.loginProcessingUrl("/login")
.loginProcessingUrl("/toLogin");
//注销,开启了注销功能,跳到首页
http.logout().logoutSuccessUrl("/");
// 防止网站工具:get,post
http.csrf().disable();//关闭csrf功能,登录失败肯定存在的原因
//开启记住我功能: cookie,默认保存两周,自定义接收前端的参数
http.rememberMe().rememberMeParameter("remember");
}
// 认证,springboot 2.1.x 可以直接使用
// 密码编码: PasswordEncoder
// 在spring Secutiry 5.0+ 新增了很多加密方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//这些数据正常应该中数据库中读
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("kuangshen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
}
}
RouterController.java
package nuc.ss.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class RouterController {
@RequestMapping({"/","/index"})
public String index() {
return "index";
}
@RequestMapping({"/login","/toLogin"})
public String toLogin() {
return "views/login";
}
@RequestMapping("/level1/{id}")
public String level1(@PathVariable("id") int id) {
return "views/level1/" + id;
}
@RequestMapping("/level2/{id}")
public String level2(@PathVariable("id") int id) {
return "views/level2/" + id;
}
@RequestMapping("/level3/{id}")
public String level3(@PathVariable("id") int id) {
return "views/level3/" + id;
}
}
login.html 核心代码
<form th:action="@{/toLogin}" method="post">
<div class="field">
<label>Username</label>
<div class="ui left icon input">
<input type="text" placeholder="Username" name="username">
<i class="user icon"></i>
</div>
</div>
<div class="field">
<label>Password</label>
<div class="ui left icon input">
<input type="password" name="password">
<i class="lock icon"></i>
</div>
</div>
<div class="field">
<input type="checkbox" name="remember"> 记住我
</div>
<input type="submit" class="ui blue submit button"/>
</form>
index.html 核心代码
<div class="ui container">
<div class="ui segment" id="index-header-nav" th:fragment="nav-menu">
<div class="ui secondary menu">
<a class="item" th:href="@{/index}">首页</a>
<!--登录注销-->
<div class="right menu">
<!--如果未登录-->
<div sec:authorize="!isAuthenticated()">
<a class="item" th:href="@{/toLogin}">
<i class="address card icon"></i> 登录
</a>
</div>
<!--如果已登录-->
<div sec:authorize="isAuthenticated()">
<a class="item">
<i class="address card icon"></i>
用户名:<span sec:authentication="principal.username"></span>
角色:<span sec:authentication="principal.authorities"></span>
</a>
</div>
<div sec:authorize="isAuthenticated()">
<a class="item" th:href="@{/logout}">
<i class="sign-out icon"></i> 注销
</a>
</div>
</div>
</div>
</div>
<div class="ui segment" style="text-align: center">
<h3>Spring Security Study by 秦疆</h3>
</div>
<div>
<br>
<div class="ui three column stackable grid">
<!-- 菜单根据用户的角色动态的实现 -->
<!-- sec:authorize="hasRole('vip1')" -->
<div class="column" sec:authorize="hasRole('vip1')">
<div class="ui raised segment">
<div class="ui">
<div class="content">
<h5 class="content">Level 1</h5>
<hr>
<div><a th:href="@{/level1/1}"><i class="bullhorn icon"></i> Level-1-1</a></div>
<div><a th:href="@{/level1/2}"><i class="bullhorn icon"></i> Level-1-2</a></div>
<div><a th:href="@{/level1/3}"><i class="bullhorn icon"></i> Level-1-3</a></div>
</div>
</div>
</div>
</div>
<div class="column" sec:authorize="hasRole('vip2')">
<div class="ui raised segment">
<div class="ui">
<div class="content">
<h5 class="content">Level 2</h5>
<hr>
<div><a th:href="@{/level2/1}"><i class="bullhorn icon"></i> Level-2-1</a></div>
<div><a th:href="@{/level2/2}"><i class="bullhorn icon"></i> Level-2-2</a></div>
<div><a th:href="@{/level2/3}"><i class="bullhorn icon"></i> Level-2-3</a></div>
</div>
</div>
</div>
</div>
<div class="column" sec:authorize="hasRole('vip3')">
<div class="ui raised segment">
<div class="ui">
<div class="content">
<h5 class="content">Level 3</h5>
<hr>
<div><a th:href="@{/level3/1}"><i class="bullhorn icon"></i> Level-3-1</a></div>
<div><a th:href="@{/level3/2}"><i class="bullhorn icon"></i> Level-3-2</a></div>
<div><a th:href="@{/level3/3}"><i class="bullhorn icon"></i> Level-3-3</a></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
四、参考文献
4.1
4.2
4.3 IDEA中下下来的 Spring Security 源码中的方法注释