SpringSecurity
1、学习目标
2、SpringSecurity简介
2.1 安全框架的概述
什么是安全框架?解决系统安全问题的框架,如果没有安全框架,我们就需要手动处理每个资源的访问控制,非常麻烦。使用安全框架,我们可以通过配置的方法实现对资源的访问控制。
2.1.2 常用安全框架
1、Spring Security:Spring家族一员。是一个能偶为基于Spring的企业级应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了
Spring Ioc(控制反转Inversion of Control,ID:Dependency Injection)依赖注入
和AOP(面向切面编程)
功能,为应用系统提供声明式安全访问控制功能,减少了企业系统安全控制编写大量重复代码工作。 2、Apache Shiro:一个功能强大且易于使用的java安全框架,提供了认证,授权,加密和会话管理。
Spring Security简介
概述
Spring Security是一个高度自定义的安全框架。利用 Spring IoC/DI和AOP功能,为系统提供了声明 式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作。使用 Spring Secruity 的原因有 很多,但大部分都是发现了 javaEE的 Servlet 规范或 EJB 规范中的安全功能缺乏典型企业应用场景。同 时认识到他们在 WAR 或 EAR 级别无法移植。因此如果你更换服务器环境,还有大量工作去重新配置你 的应用程序。使用 Spring Security解决了这些问题,也为你提供许多其他有用的、可定制的安全功能。 正如你可能知道的两个应用程序的两个主要区域是“认证”和“授权”(或者访问控制)。这两点也是 Spring Security 重要核心功能。“认证”,是建立一个他声明的主体的过程(一个“主体”一般是指用户, 设备或一些可以在你的应用程序中执行动作的其他系统),通俗点说就是系统认为用户是否能登录。 “授权”指确定一个主体是否允许在你的应用程序执行一个动作的过程。通俗点讲就是系统判断用户是否 有权限去做某些事情。
历史
Spring Security 以“The Acegi Secutity System for Spring”的名字始于2003年年底。其前身为 acegi 项目。起因是 Spring 开发者邮件列表中一个问题,有人提问是否考虑提供一个基于 Spring 的安全实 现。限制于时间问题,开发出了一个简单的安全实现,但是并没有深入研究。几周后,Spring 社区中其 他成员同样询问了安全问题,代码提供给了这些人。2004 年 1 月份已经有 20 人左右使用这个项目。随 着更多人的加入,在 2004 年 3 月左右在 sourceforge 中建立了一个项目。在最开始并没有认证模块, 所有的认证功能都是依赖容器完成的,而 acegi 则注重授权。但是随着更多人的使用,基于容器的认证 就显现出了不足。acegi 中也加入了认证功能。大约 1 年后 acegi 成为 Spring子项目。在 2006 年 5 月 发布了 acegi 1.0.0 版本。2007 年底 acegi 更名为Spring Security。
快速入门
导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xxxx</groupId>
<artifactId>springsecurity-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springsecurity-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--spring security 组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--web 组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- test 组件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
前端页面
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
用户名:<input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
<input type="submit" value="登录" />
</form>
</body>
</html>
访问页面
导入spring-boot-starter-security 启动器后,Spring Security 已经生效,默认拦截全部请求,如果用 户没有登录,跳转到内置登录页面
默认的 username 为 user,password 打印在控制台中。 在浏览器中输入账号和密码后会显示 login.html 页面内容。
UserDetailsService详解
当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的。而在实际项目中账号和密 码都是从数据库中查询出来的。所以我们要通过自定义逻辑控制认证逻辑。如果需要自定义逻辑时,只 需要实现 UserDetailsService 接口即可。接口定义如下:
public interface UserDetailsService {
UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
返回值
返回值 UserDetails 是一个接口,定义如下
public interface UserDetails extends Serializable {
//获取所有权限
Collection<? extends GrantedAuthority> getAuthorities();
//获取密码
String getPassword();
//获取用户名
String getUsername();
//是否账号过期
boolean isAccountNonExpired();
//是否账号被锁定
boolean isAccountNonLocked();
//凭证(密码)是否过期
boolean isCredentialsNonExpired();
//是否可用
boolean isEnabled();
}
UserDetails
的实例就只能返回接口的实现类。SpringSecurity 中提供了如下的实例。对于 我们只需要使用里面的 User 类即可。注意 User 的全限定路径是:org.springframework.security.core.userdetails.User
此处经常和系统中自己开发的 User 类弄 混。
其中构造方法有两个,调用其中任何一个都可以实例化 UserDetails 实现类 User 类的实例。而三个参数的构造方法实际上也是调用 7 个参数的构造方法。
- username :用户名
- password :密码
- authorities :用户具有的权限。此处不允许为 null
此处的用户名应该是客户端传递过来的用户名。而密码应该是从数据库中查询出来的密码。Spring Security 会根据 User 中的 password 和客户端传递过来的 password 进行比较。如果相同则表示认证 通过,如果不相同表示认证失败。