springboot学习之授权Spring Security
SpringSecurity核心功能:认证、授权、攻击防护(防止伪造身份)
涉及的依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
1 2 3 4 | <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> |
新建一个项目,添加如上依赖【添加依赖之后默认开始授权验证】,在控制器controller中测试,指定url,比如
1 2 3 4 5 6 7 | @Controller public class UserController { @RequestMapping (value= "/hello" ) @ResponseBody public String hello(){ return "=======Welcome to HelloWorld==============" ;} } |
如上,原本启动项目后,在地址栏中输入http://localhost:8080/hello应该显示返回的内容
然而此次加了安全验证后,不管url中访问的地址是什么,hello还是hello111,均返回login页面,如下
此时系统都没有连DB,用户名和密码是什么?
控制台中有消息,比如Using generated security password: 76dade1c-f190-44f8-915c-7a6b6917fb9a【每次随机生成的密码】
将用户名 user 和 密码 76dade1c-f190-44f8-915c-7a6b6917fb9a 填入上面对话框中,点击按钮Sign in
若之前访问的页面是控制器中配置的页面http://localhost:8080/hello
则此时能成功显示
若之前访问的页面是其他的,控制器中未配置的,则重定向后返回页面不存在。
当前自己的项目中,总不能用系统生成的密码进行登录获得权限,那不要被别人笑死。
进阶阶段:
我简单创建了一张表,希望该表的人输入匹配的用户名和密码后,方能登录。
1 2 3 4 5 6 7 8 9 10 11 | CREATE TABLE `admin_user`( `id` int (4) NOT NULL AUTO_INCREMENT, `username` VARCHAR (100), ` password ` VARCHAR (100), `role` VARCHAR (100), `realname` VARCHAR (100), `mobile` VARCHAR (2000), `state` BIT default 0, `info` VARCHAR (200), PRIMARY KEY (`id`) )ENGINE=InnoDB AUTO_INCREMENT=300; |
塞了几条数据进去,然后我希望用户在页面上进行登录,那我必须还要创建一个User对象,所谓登录就是传入username和password匹配的场景,只要匹配,就登录成功,跳转到之前的url
1 2 3 4 5 | public class User { private int id; private String name; private String password; 省略 getter and setter} |
1 2 3 4 | public interface UserService { User login(String name, String password); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Service public class UserServiceImpl implements UserService { @Autowired private JdbcTemplate jdbcTemplate; @Override public User login(String name, String password) { String sql = "select * from admin_user where username =? and password = ?" ; User user =jdbcTemplate.queryForObject(sql, new UserRowMapper(),name,password); return user; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class UserRowMapper implements RowMapper<User> { @Override public User mapRow(ResultSet resultSet, int i) throws SQLException { //此处要使用表中的字段,不能使用属性 int id =resultSet.getInt( "id" ); String username = resultSet.getString( "username" ); String password = resultSet.getString( "password" ); //String role = resultSet.getString("role"); User user = new User(); user.setId(id); user.setName(username); user.setPassword(password); return user; } } |
登录的方法啪啪啪很快就写好了,我要怎么让系统知道,所有的请求,要先进行登录呢,登录的URL是什么?
先看看别人的代码,貌似是实现了UserDetailsService 接口,而点进去发现该接口就一个方法
1 2 3 4 5 | package org.springframework.security.core.userdetails; public interface UserDetailsService { UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException; } |
通过一个String类型的变量val1,获取用户的详细信息。。。怎么跟我想的不太一样?
再点进去发现UserDetails 也是一个接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package org.springframework.security.core.userdetails; import java.io.Serializable; import java.util.Collection; import org.springframework.security.core.GrantedAuthority; public interface UserDetails extends Serializable { Collection<? extends GrantedAuthority> getAuthorities(); String getPassword(); String getUsername(); boolean isAccountNonExpired(); boolean isAccountNonLocked(); boolean isCredentialsNonExpired(); boolean isEnabled(); } |
一个集合,收集权限,结合做过的项目,有的权限是超级管理员,有的权限是普通管理员,又或者有的删,有新增,有更新等等权限;两个返回String的方法;
还有判断账户是否过期,被锁,验证是否过期,是否开启了。。。
看来光看别人的代码,还是丈二和尚摸不着头脑呢,去看看官方文档吧
https://spring.io/projects/spring-security
https://spring.io/guides/topicals/spring-security-architecture
英文原文我就不粘贴了,翻译过来,大意就是:
应用程序权限归结于两个独立的问题:
1. 你是谁
2. 你有什么样的权限
一般叫法是权限控制 或者 授权
下面开始讲框架中的源码,通过看源码可以了解设计的思路
1. 授权策略中主要的接口是AuthenticationManager
,并且只有一个方法
1 2 3 4 5 6 | public interface AuthenticationManager { Authentication authenticate(Authentication authentication) throws AuthenticationException; } |
验证管理员在方法authenticate()可以做三件事
a. 输入的信息是有效的当事人,验证通过,返回Authentication
b. 输入的信息是无效的当事人,验证不通过,返回AuthenticationException
c. 无法判断的时候,返回一个null
看到这儿,就觉得我想通过查询 用户名 = 输入的用户名 且 密码 =输入密码的想法真是异想天开了。
Filter Chains,过滤链,默认对所有的范文url进行过滤,意味着打开这个网站的任何链接,都弹出授权页面
而如果像如下的例子,则可以在foo下的下url不进行授权验证,说白了,不登录,这个url下也可以访问。 想想日常使用场景,比如总要有个注册页面吧,不能全面链接都要求登录。不注册如何登录呢?
1 2 3 4 5 6 7 8 9 | @Configuration @Order (SecurityProperties.BASIC_AUTH_ORDER - 10 ) public class ApplicationConfigurerAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher( "/foo/**" ) ...; } } |
用户登录了之后,要怎么查看个人信息,传入@AuthenticationPrincipal,当事人对象Principal principal
1 2 3 4 | @RequestMapping ( "/foo" ) public String foo( @AuthenticationPrincipal User user) { ... // do stuff with user } |
1 2 3 4 5 6 | @RequestMapping ( "/foo" ) public String foo(Principal principal) { Authentication authentication = (Authentication) principal; User = (User) authentication.getPrincipal(); ... // do stuff with user } |
使用规则介绍完了,花了两天把授权一个可用的项目的代码整理出来,贴上github路径
https://github.com/JasmineQian/buglist
其中用的是springboot 2.1.2 Realease 版本,和以前的版本稍微有一点区别,比如必须对密码加密校验,So存进去的密码处,必须加密之后存入数据库
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
程序中验证的用户名和密码
自己建一张表,叫做qa_user,添加如下数据
2 admin $2a$10$A4EZrzoXqj4mVyXiw/fsp.mJ.Ne5aVAMWrMK0mAb2zY7lJ/H6Jryi admin ROLE_USER,ROLE_ADMIN

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?