Spring-Security
本文测试所用demo资源已上传:https://download.youkuaiyun.com/download/qq_42295733/12125241
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
官网:https://www.springcloud.cc/spring-security.html
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
用户授权和认证
路由控制
@Controller
public class RouterController {
@RequestMapping({"/","/index","/index.html"})
public String index() {
return "index";
}
@RequestMapping("/toLogin")
public String toLogin() {
return "/views/login";
}
@RequestMapping("/level1/{id}")
private String level1(@PathVariable("id") int id) {
return "/views/level1/" + id;
}
@RequestMapping("/level2/{id}")
private String level2(@PathVariable("id") int id) {
return "/views/level2/" + id;
}
@RequestMapping("/level3/{id}")
private String level3(@PathVariable("id") int id) {
return "/views/level3/" + id;
}
}
到目前为止,我们的WebSecurityConfig仅包含有关如何验证用户身份的信息。Spring Security如何知道我们要求所有用户都经过身份验证?Spring Security如何知道我们想要支持基于表单的身份验证?原因是WebSecurityConfigurerAdapter
在configure(HttpSecurity http)
方法中提供了一个默认配置
@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();
}
}
上述规定了各个级别角色所能访问的页面,运行测试一下
未分配角色前,点击任意一个页面后,自动在url后添加/login
,这便是我们的配置生效了
现在继续重写一个方法protected void configure(AuthenticationManagerBuilder auth)
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//此处采用内存验证用户账号密码,也可以用数据库
auth.inMemoryAuthentication()//各个用户分配角色权限
.withUser("lizeyu").password("111111").roles("vip2", "vip3")
.and()
.withUser("root").password("111111").roles("vip1", "vip2", "vip3")
.and()
.withUser("guest").password("111111").roles("vip1");
}
运行后会发现报一个错误
采用普通用户登录
提醒我们密码需要设置加密,完整代码如下
//认证:springboot 2.1.X 可以直接使用
//密码编码:PasswordEncoder()
//在spring security 5.0+,新增了很多的加密方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("lizeyu").password(new BCryptPasswordEncoder().encode("111111")).roles("vip2", "vip3")
.and()
.withUser("root").password(new BCryptPasswordEncoder().encode("111111")).roles("vip1", "vip2", "vip3")
.and()
.withUser("guest").password(new BCryptPasswordEncoder().encode("111111")).roles("vip1");
}
再次运行依然是普通用户登录,访问level1下的目录,由上可知是vip1角色才可以
这样目的达到,OJBK
增加注销功能
//注销
http.logout();
采用semantic-ui作为样板
<link href="https://cdn.bootcss.com/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet">
<!--注销-->
<a class="item" th:href="@{/logout}">
<i class="sign-out icon"></i>注销
</a>
测试
注销成功,OJBK
如果我们想让注销后跳到首页:
//注销,开启了注销功能,跳到首页
http.logout().logoutSuccessUrl("/");
为实现不同权限的用户仅显示自己拥有权限的页面,我们引入thymeleaf与secrity整合的包
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
导入sec
命名空间
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
实现未登录仅显示登录按钮,登录成功显示用户名和注销按钮
<!--如果未登录-->
<!--Authenticated 表示用户已经认证-->
<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">
用户名:<span sec:authentication="name"></span>
</a>
</div>
<div sec:authorize="isAuthenticated()">
<!--注销-->
<a class="item" th:href="@{/logout}">
<i class="sign-out icon"></i>注销
</a>
</div>
此时会发现一个问题,我们注销后无法返回首页,会进入到一个404页面,可能原因是我们采用的提交请求是get
,security会认为明文传输不安全,自动帮我们屏蔽,这时我们不能觉得我们代码错了,而是配置问题
//关闭防止网站攻击
http.csrf().disable();
OJBK
实现不同权限用户不同页面
sec:authorize="hasRole('vip2')" <!--加入显示标签内即可-->
这样我们的权限控制就完成了
记住我功能实现
//记住我功能实现
http.rememberMe();
定制我们的登录页面
//定制登陆页面
http.formLogin().loginPage("/toLogin");
ok!
在自定义登录界面添加记住我按钮
//自定义记住我标签的name
http.rememberMe().rememberMeParameter("remember");
<div class="field">
<input type="checkbox" name="remember-me">记住我
</div>
如果不自定义记住我的参数,观看源码可知默认的参数名为remember-me
,即可自动后台帮我们设置cookie中记住我的参数
本部分只是对SpringSecurity初步的入门讲解,真正企业开发整合:https://www.cnblogs.com/cao-lei/p/13298394.html
学习资源:https://blog.youkuaiyun.com/qq_42640067/article/details/113062222