5. Spring Security
5.1 简介
- Spring Security 是针对 Spring 项目的安全框架,也是 SpringBoot 底层安全模块的默认技术选型,启动器为 spring-boot-starter-security
- 主要类
- WebSecurityConfigurerAdapter: 自定义的 Security 策略
- AuthenticationManagerBuilder: 自定义认证策略
- @EnableWebSecurity: 开启 WebSecurity 模式
5.2 认证和授权
-
导入依赖
<!--thymeleaf-security整合包--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> <version>3.0.4.RELEASE</version> </dependency>
-
编写配置类
@EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { // 授权 @Override protected void configure(HttpSecurity http) throws Exception { // 请求授权的规则 http.authorizeRequests() // 首页所有人都能访问,功能页对应的人都能访问 .antMatchers("/").permitAll() // vip1 只能访问 level1 目录下的页面 .antMatchers("/level1/**").hasAnyRole("vip1") // vip2 只能访问 level2 目录下的页面 .antMatchers("/level2/**").hasAnyRole("vip2") // vip3 只能访问 level3 目录下的页面 .antMatchers("/level3/**").hasAnyRole("vip3"); // 没有权限,跳转到默认登录页 http.formLogin(); } // 认证 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 密码需要编码,否则会报500错误 auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) // admin 有 vip1, vip2, vip3 的全部认证 .withUser("admin").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2","vip3") .and() // why 有 vip2, vip3 的认证 .withUser("why").password(new BCryptPasswordEncoder().encode("123")).roles("vip2","vip3") .and() // guest 有 vip1 的认证 .withUser("guest").password(new BCryptPasswordEncoder().encode("123")).roles("vip1"); } }
5.3 注销和权限
-
配置类添加注销
// SecurityConfig --> configure(HttpSecurity http) // 注销,跳转到首页 // 关闭 csrf,页面直接进入首页,否则进入提示页 "Are you sure want to logout" http.csrf().disable(); // 防止跨站攻击 http.logout().logoutSuccessUrl("/");
-
修改 html
-
添加引用
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
-
修改元素
<!--未登录界面显示登录按钮--> <a th:href="@{/toLogin}" class="nav-item" active-color="red" sec:authorize="!isAuthenticated()"> 登录 </a> <!--已登录界面显示用户名--> <a class="nav-item" active-color="red" sec:authorize="isAuthenticated()"> 用户名:<span sec:authentication="name"></span> </a> <!--已登录界面显示注销按钮--> <a th:href="@{/logout}" class="nav-item" active-color="rebeccapurple" sec:authorize="isAuthenticated()"> 注销 </a>
<!--有相关授权的角色才可以看到对应的界面--> <div class="col-xs-4" sec:authorize="hasRole('vip1')">...</div> <div class="col-xs-4" sec:authorize="hasRole('vip2')">...</div> <div class="col-xs-4" sec:authorize="hasRole('vip3')">...</div>
-
5.4 首页和 Remeber me 的定制
-
配置类文章来源:https://uudwc.com/A/8dndG
// SecurityConfig --> configure(HttpSecurity http) // 定制登录登录页 http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login").usernameParameter("username").passwordParameter("password"); // 开启网页记住用户名密码,默认保存两周 // 自定义 remember me http.rememberMe().rememberMeParameter("remember");
-
loginPage("/toLogin")
: 指定登录界面 -
loginProcessingUrl("/login")
: 指定登录表单的提交地址 -
usernameParameter("username")
: 指定用户名的 html 元素的 属性值 -
passwordParameter("password")
: 指定密码的 html 元素的 属性值 - 请求登录页一定要使用 POST 请求
-
-
html 元素文章来源地址https://uudwc.com/A/8dndG
<!--跳转到登录页面--> <a th:href="@{/toLogin}" class="nav-item" active-color="red" sec:authorize="!isAuthenticated()">登录</a> <!--登录请求的 form--> <form method="post" th:action="@{/login}"> <input type="text" name="username" placeholder="Email"> <input type="password" name="password" placeholder="Password"> <input type="checkbox" name="remember">记住我</input></a> <button type="submit" class="button">登录</button> </form>