Spring Security 是 Spring 家族中的一个安全管理框架,实际上,在 Spring Boot 出现之前,Spring Security 就已经发展了多年了,但是使用的并不多,安全管理这个领域,一直是 Shiro 的天下。
相对于 Shiro,在 SSM/SSH 中整合 Spring Security 都是比较麻烦的操作,所以,Spring Security 虽然功能比 Shiro 强大,但是使用反而没有 Shiro 多(Shiro 虽然功能没有 Spring Security 多,但是对于大部分项目而言,Shiro 也够用了)。
自从有了 Spring Boot 之后,Spring Boot 对于 Spring Security 提供了 自动化配置方案,可以零配置使用 Spring Security。
安全简介
一般来说,常见的安全管理技术栈的组合是这样的:
SSM + Shiro
Spring Boot/Spring Cloud + Spring Security
在 Web 开发中,安全一直是非常重要的一个方面。安全虽然属于应用的非功能性需求,但是应该在应用开发的初期就考虑进来。如果在应用开发的后期才考虑安全的问题,就可能陷入一个两难的境地:一方面,应用存在严重的安全漏洞,无法满足用户的要求,并可能造成用户的隐私数据被攻击者窃取;另一方面,应用的基本架构已经确定,要修复安全漏洞,可能需要对系统的架构做出比较重大的调整,因而需要更多的开发时间,影响应用的发布进程。因此,从应用开发的第一天就应该把安全相关的因素考虑进来,并在整个应用的开发过程中。
市面上存在比较有名的:Shiro,Spring Security
!
注意,这只是一个推荐的组合而已,如果单纯从技术上来说,无论怎么组合,都是可以运行的。
这里需要阐述一下的是,每一个框架的出现都是为了解决某一问题而产生了,那么 Spring Security 框架的出现是为了解决什么问题呢?
首先我们看下它的官网介绍:Spring Security 官网地址
1 | Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications. |
怎么解决之前写权限代码繁琐,冗余的问题,一些主流框架就应运而生而 Spring Scecurity 就是其中的一种。
Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。
一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。
用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。
用户认证一般要求用户提供用户名和密码。
系统通过校验用户名和密码来完成认证过程。
用户授权指的是验证某个用户是否有权限执行某个操作。
在一个系统中,不同用户所具有的权限是不同的。
比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。
一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。
对于上面提到的两种应用情景,Spring Security 框架都有很好的支持。在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP
等。在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表
(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制
。
实战测试
实验环境搭建
以前我们都是用拦截器、过滤器实现安全控制的,都是大量的原生代码,冗余~
1、新建一个初始的 springboot 项目 web 模块,勾选需要用的功能模块
2、导入静态资源
静态资源结构
3、编写 controller 跳转
1 | package com.itjing.controller; |
4、测试实验环境是否 OK!
认识 SpringSecurity
Spring Security 是针对 Spring 项目的安全框架,也是 Spring Boot 底层安全模块默认的技术选型,他可以实现强大的 Web 安全控制,对于安全控制,我们仅需要引入 spring-boot-starter-security
模块,进行少量的配置,即可实现强大的安全管理!
记住几个类:
WebSecurityConfigurerAdapter:
自定义 Security 策略AuthenticationManagerBuilder:
自定义认证策略@EnableWebSecurity:
开启 WebSecurity 模式
Spring Security 的两个主要目标是 “认证”
和 “授权”
(访问控制)。
“认证”(Authentication)
身份验证是关于验证您的凭据,如用户名/用户 ID 和密码,以验证您的身份。
身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。
“授权” (Authorization)
授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。
这个概念是通用的,而不是只在 Spring Security 中存在。
认证和授权
目前,我们的测试环境,是谁都可以访问的,我们使用 Spring Security 增加上认证和授权的功能
1、引入 Spring Security 模块
1 | <!--springsecurity--> |
只要加入依赖,项目的所有接口都会被自动保护起来。
再次启动访问项目的接口的时候 ,发现需要登录之后才能访问
当用户从浏览器发送请求访问项目接口
时,服务端会返回 302
响应码,让客户端重定向到 /login
页面,用户在 /login
页面登录,登陆成功之后,就会自动跳转到项目接口
。
另外,也可以使用 POSTMAN
来发送请求,使用 POSTMAN
发送请求时,可以将用户信息放在请求头中(这样可以避免重定向到登录页面
):
通过以上两种不同的登录方式,可以看出,Spring Security 支持两种不同的认证方式:
可以通过 form 表单来认证
可以通过 HttpBasic 来认证
2、编写 Spring Security 配置类
参考官网:https://spring.io/projects/spring-security
查看我们自己项目中的版本,找到对应的帮助文档:Spring Security 5.4.2 文档
3、编写基础配置类
1 | package com.itjing.config; |
4、定制请求的授权规则
在配置类的 configure() 方法中定义
1 |
|
5、测试一下:发现除了首页都进不去了!因为我们目前没有登录的角色,因为请求需要登录的角色拥有对应的权限才可以!
6、在 configure() 方法中加入以下配置,开启自动配置的登录功能!
1 | // 开启自动配置的登录功能 |
7、测试一下:发现,没有权限的时候,会跳转到登录的页面!
8、用户配置
默认情况下,登录的用户名是 user
,密码则是项目启动时随机生成的字符串,可以从启动的控制台日志中看到默认密码
这个随机生成的密码,每次启动时都会变。
对登录的用户名/密码进行配置,有三种
不同的方式:
在 application.properties 中进行配置
通过 Java 代码配置在内存中
通过 Java 从数据库中加载
配置文件配置用户名/密码
可以直接在 application.properties 文件中配置用户的基本信息:
1 | # 配置springsecurity用户名和密码 |
Java 配置用户名/密码
我们可以定义认证规则,重写 configure(AuthenticationManagerBuilder auth)
方法
1 | //定义认证规则 |
测试,我们可以使用这些账号登录进行测试!发现会报错!
1 | java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" |
原因,我们要将前端传过来的密码进行某种方式加密,否则就无法登录,修改代码
1 | //定义认证规则 |
Spring Security 中提供了 BCryptPasswordEncoder 密码编码工具,可以非常方便的实现密码的加密加盐,相同明文加密出来的结果总是不同,这样就不需要用户去额外保存盐
的字段了,这一点比 Shiro 要方便很多。
测试,发现,登录成功,并且每个角色只能访问自己认证下的规则!搞定!
登录配置
这里是参考博客园的一篇文章的:点击进入文章
对于登录接口,登录成功后的响应,登录失败后的响应,我们都可以在 WebSecurityConfigurerAdapter 的实现类中进行配置。例如下面这样:
1 |
|
我们可以在 successHandler 方法中,配置登录成功的回调,如果是前后端分离开发的话,登录成功后返回 JSON 即可,同理,failureHandler 方法中配置登录失败的回调,logoutSuccessHandler 中则配置注销成功的回调。
权限控制和注销
1、开启自动配置的注销的功能
1 | //定制请求的授权规则 |
2、我们在前端,增加一个注销的按钮,index.html 导航栏中
1 | <a class="item" th:href="@{/logout}"> |
3、我们可以去测试一下,登录成功后点击注销,会提醒我们是否注销,发现注销完毕会跳转到登录页面!
4、但是,我们想让他注销成功后,依旧可以跳转到首页,该怎么处理呢?
1 | // .logoutSuccessUrl("/"); 注销成功来到首页 |
5、测试,注销完毕后,发现跳转到首页 OK
6、我们现在又来一个需求
用户没有登录的时候,导航栏上只显示登录按钮,用户登录之后,导航栏可以显示登录的用户信息及注销按钮!还有就是,比如 jinggege 这个用户,它只有 vip2,vip3 功能,那么登录则只显示这两个功能,而 vip1 的功能菜单不显示!这个就是真实的网站情况了!该如何做呢?
我们需要结合thymeleaf中的一些功能
thymeleaf 常用命名空间,需要的兄弟请自取,顺便顶下我,让跟多的朋友看到:
1 | # thymeleaf常用命名空间 |
sec:authorize=”isAuthenticated()”:是否认证登录!来显示不同的页面
Maven 依赖:
1 | <!--thymeleaf-springsecurity--> |
7、修改我们的 前端页面
导入命名空间
1 | xmlns:sec="http://www.thymeleaf.org/extras/spring-security" |
修改导航栏,增加认证判断
1 | <!--登录注销--> |
8、重启测试,我们可以登录试试看,登录成功后确实,显示了我们想要的页面
9、解决注销 404 问题
因为它默认防止 csrf 跨站请求伪造,因为会产生安全问题,我们可以将请求改为 post 表单提交,或者在 spring security 中关闭 csrf 功能;
我们试试:在配置中增加 http.csrf().disable();
1 | http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求 |
10、我们继续将下面的角色功能块认证完成
1 | <div class="column" sec:authorize="hasRole('vip1')"> |
11、测试一下!
12、权限控制和注销搞定!
记住我
现在的情况,我们只要登录之后,关闭浏览器,再登录,就会让我们重新登录,但是很多网站的情况,就是有一个记住密码的功能,这个该如何实现呢?很简单!
1、开启记住我功能
1 | //定制请求的授权规则 |
2、我们再次启动项目测试一下,发现登录页多了一个记住我功能,我们登录之后关闭浏览器,然后重新打开浏览器访问,发现用户依旧存在!
思考:如何实现的呢?其实非常简单
我们可以查看浏览器的 cookie
3、我们点击注销的时候,可以发现,spring security 帮我们自动删除了这个 cookie
4、结论:登录成功后,将 cookie 发送给浏览器保存,以后登录带上这个 cookie,只要通过检查就可以免登录了。如果点击注销,则会删除这个 cookie!
定制登录页
现在这个登录页面都是 spring security 默认的,怎么样可以使用我们自己写的 Login 界面呢?
1、在刚才的登录页配置后面指定 loginpage
1 | http.formLogin().loginPage("/toLogin"); |
2、然后前端也需要指向我们自己定义的 login 请求
1 | <a class="item" th:href="@{/toLogin}"> |
3、我们登录,需要将这些信息发送到哪里,我们也需要配置,login.html 配置提交请求及方式,方式必须为 post
在 loginPage()源码中的注释上有写明:
1 | <form th:action="@{/user/login}" method="post"> |
4、这个请求提交上来,我们还需要验证处理,怎么做呢?
我们可以查看 formLogin()方法的源码!我们配置接收登录的用户名和密码的参数!
1 | http.formLogin() |
5、在登录页增加记住我的多选框
1 | <input type="checkbox" name="remember" /> 记住我 |
6、后端验证处理!
1 | //定制记住我的参数! |
7、测试,OK
完整配置代码
1 | package com.itjing.config; |
后续更新更多功能!
发布时间: 2020-12-23
最后更新: 2024-06-24
本文标题: SpringBoot集成SpringSecurity
本文链接: https://blog-yilia.xiaojingge.com/posts/ed847ce1.html
版权声明: 本作品采用 CC BY-NC-SA 4.0 许可协议进行许可。转载请注明出处!
