Spring Security
Spring Security
- Web开发中,安全First
- 非功能需求(没它也能跑)
- 应在设计之初考虑
依赖
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
环境搭建
- 静态资源
- 链接: https://pan.baidu.com/s/1ee75wHjZL4rJYQd003cbHg
- 提取码: abcd
编写路由Controller,用于页面跳转
@Controller
public class RouterController {
@RequestMapping({"/", "/index"})
public String index() {
return "index";
}
@RequestMapping("/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;
}
}
用户认证和授权
编写Security的config类处理认证和授权
@EnableWebSecurity
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");
// 没有权限默认到登录页
http.formLogin();
}
// 认证
// 登录成功但认证失败, 缺少密码编码: PasswordEncoder
// SpringSecurity 有许多加密方式
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 正常是从数据库读
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("lct").password(new BCryptPasswordEncoder().encode("1")).roles("vip1", "vip3")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("1")).roles("vip1", "vip2", "vip3")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("1")).roles("vip1");
}
}
注销
在授权位置添加注销支持
// 授权
@Override
protected void configure(HttpSecurity http) throws Exception {
// ...
// 开启了注销功能
// 默认会走"/logout"请求
http.csrf().disable(); // 关闭后可通过Get方式请求(有时需要, 比如说注销突然404, 则大概率需要添加)
http.logout().logoutSuccessUrl("/");
}
前端写一个注销请求的按钮
<!-- 如果已登录, 显示注销按钮 -->
<a class="item" th:href="@{/logout}">
<i class="sign-out icon"></i> 注销
</a>
权限控制
添加依赖
<!-- Spring Security & Thymeleaf -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
index.html添加命名空间
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
登录与否显示对应按钮
<!--semantic-ui-->
<link href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet">
<!--登录注销-->
<div class="right menu">
<div sec:authorize="!isAuthenticated()">
<!-- 如果未登录, 显示登录按钮 -->
<a class="item" th:href="@{/login}">
<i class="address card icon"></i> 登录
</a>
</div>
<div sec:authorize="isAuthenticated()">
<a class="item">
用户名: <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>
根据身份显示可进入的页面(level1,其他一样)
<!-- 菜单动态实现 -->
<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>
Remember Me
在授权位置添加记住我支持
// 授权
@Override
protected void configure(HttpSecurity http) throws Exception {
// ...
// 开启记住我功能, 默认保存2周
http.rememberMe();
}

自定义
配置
// 自定义接收前端的参数
http.rememberMe().rememberMeParameter("remember");
前端参数
<input type="checkbox" name="remember">Remember Me
首页定制
配置自定义的首页
// 授权
@Override
protected void configure(HttpSecurity http) throws Exception {
// ...
http.formLogin()
.loginPage("/toLogin")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login");
// ...
}
前端传来的参数
<div class="ui placeholder segment">
<div class="ui column very relaxed stackable grid">
<div class="column">
<div class="ui form">
<form th:action="@{/login}" 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">
<label>
<input type="checkbox" name="remember">
</label>Remember Me
</div>
<input type="submit" class="ui blue submit button"/>
</form>
</div>
</div>
</div>
</div>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?