Spring Security源码初步分析
Spring Security是一个高度自定义的安全框架,它和Shiro很像。利用Spring IOC/DI和AOP功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作。
SpringBoot整合SpringSecurity
第一个SpringSecurity程序
我们需要先导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>
</dependencies>
建立SpringBoot的启动类,再添加一个login.html内容可以随便写
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class,args);
}
}
启动之后打开浏览器,输入localhost:8080/login.html就会出现一个登陆界面
账号一般默认是user,密码的话呢,打开IDEA,下面控制台就会显示。每次显示的密码都不一样。
自定义用户名和密码
通过修改配置文件:application.properties/yml就可以做到
spring.security.user.name=smallming
spring.security.user.password=smallming
UserDetailsService
在我们什么都没有配置的时候,账号和密码是由Spring Security定义生成的。而在实际项目中,账号和密码其实都是从数据库里面查询出来的。 所以我们要通过自定义逻辑控制认证逻辑。
那么现在我需要自定义逻辑,那么我就只需要实现UserDetailsService接口就可以了。
我们从这个接口可以看到,返回值是一个UserDetails的接口,我们点进源码看一看
要想返回UserDetails的实例就只能返回接口的实现类。
其中构造方法有两个,调用其中任何一个都可以实例化UserDetails实现类User类的实例。而三个参数的构造方法实际上也是调用7个参数的构造方法。有时间的话可以根据package org.springframework.security.core.userdetails路径点进源码看一看
此处的用户名应该是客户端传递过来的用户名。而密码应该是从数据库中查询出来的密码。Spring Security会根据User中的password和客户端传递过来的password进行比较。如果相同则表示认证通过,如果不相同表示认证失败。
authorities里面的权限对于后面的授权操作是很有必要的,包含的所有内容为此用户具有的权限,如有里面没有包含某个权限,而在做某个事情时必须包含某个权限则会出现403。通常都是通过AuthorityUtils.commaSeparatedStringToAuthorityList(“”)来创建authorities集合对象的。参数是一个字符串,多个权限使用逗号分隔。
PasswordEncoder密码解析器
Spring Security要求容器中必须有PasswordEncoder实例(客户端密码和数据库密码是否匹配是由Spring Security 去完成的,Security中还没有默认密码解析器)。所以当自定义登录逻辑时要求必须给容器注入PaswordEncoder的bean对象
我们来看看接口?
BCryptPasswordEncoder
BCryptPasswordEncoder是Spring Security官方推荐的密码解析器,平时多使用这个解析器。
BCryptPasswordEncoder是对bcrypt强散列方法的具体实现。是基于Hash算法实现的单向加密。可以通过strength控制加密强度,默认10.
代码实现
@SpringBootTest
@RunWith(SpringRunner.class)
public class Test {
@Test
public void test(){
//创建解析器
PasswordEncoder passwordencoder = new BCryptPasswordEncoder();
//对密码进行加密
String password = passwordencoder.encode("369613719");
System.out.println("password : "+password);
//判断原字符加密后和内容是否匹配
boolean result = passwordencoder.matches("369613719",password);
System.out.println("result : "+result);
}
}