Spring Security 介绍

Spring Security 是一个功能强大且可高度自定义的身份验证和访问控制框架。它是保护基于 Spring 的应用程序的事实上的标准。
Spring Security 是一个专注于为 Java 应用程序提供身份验证和授权的框架。与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求。

Spring Security 特点

1.对身份验证和授权的全面和可扩展的支持
2.防止会话固定,点击劫持,跨站点请求伪造等攻击
3.Servlet API 集成
4.可选与 Spring Web MVC 集成

在 Spring Boot 项目中添加 Spring Security

创建 Spring Boot 已经在之前的博客中提到了,详情请查看 Spring Boot 入门

功能:创建静态页面,通过 Spring Security 权限管理,熟悉 Spring Security 的功能及配置

引入 maven 依赖

Spring Security 依赖如下

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.security</groupId>
<artifactId>spring-security</artifactId>
<version>0.1.0</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<properties>
<java.version>1.8</java.version>
</properties>


<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

创建静态页面

创建三个静态页面:主页、hello 页面和登录页面
注意:静态文件不要 WEB-INF 下,应用服务器把 WEB-INF 指为禁访目录,即直接在浏览器里是不能访问到的
src/main/resources/templates/home.html

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example</title>
</head>
<body>
<h1>欢迎!</h1>
<p>点击 <a th:href="@{/hello}">这里</a>进入 hello 页面.</p>
</body>
</html>

主页中,在 Thymeleaf 模板定义跳转到 hello 页面
src/main/resources/templates/hello.html

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Hello World!</title>
</head>
<body>
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
<form th:action="@{/logout}" method="post">
<input type="submit" value="Sign Out"/>
</form>
</body>
</html>

登录页面
src/main/resources/templates/login.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example </title>
</head>
<body>
<div th:if="${param.error}">
Invalid username and password.
</div>
<div th:if="${param.logout}">
You have been logged out.
</div>
<form th:action="@{/login}" method="post">
<div><label> User Name : <input type="text" name="username"/> </label></div>
<div><label> Password: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
</body>
</html>

配置 Spring MVC 的配置类

Web应用程序基于 Spring MVC,配置 Spring MVC 并设置视图控制器访问页面

src/main/java/hello/MvcConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package hello;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

/**
* 配置预先配置了响应状态代码的简单自动控制器和/或视图以呈现响应主体。
* 覆盖 WebMvcConfigurer 中的 addViewControllers 同名方法
* 添加了四个视图控制器,前两个引用名称为 “home”(在其中定义 home.html)的视图,
* 另一个引用名为 “hello”(在其中定义 hello.html)的视图,
* 最后一个引用另一个名为 “login” 的视图
* @param registry
*/
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}

}

设置Spring Security

src/main/java/hello/WebSecurityConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package hello;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 该方法定义 url 的访问权限,登录路径,注销
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll() //任何人(包括没有经过验证的)都可以访问 "/" 和 "/home"
// .antMatchers("/admin/**").hasRole("ADMIN") // "/admin/" 开头的 URL 必须要是管理员用户,譬如 ”admin” 用户
.anyRequest().authenticated() //所有其他的 URL 都需要用户进行验证
.and()
.formLogin() //使用 Java 配置默认值设置了基于表单的验证。使用 POST 提交到"/login"时,需要用 "username" 和 "password" 进行验证
.loginPage("/login") //指定在需要登录时将用户发送到的URL
.permitAll() //用户可以访问 formLogin() 相关的任何URL
.and()
.logout() //注销
.permitAll(); //用户可以访问 logout() 相关的任何URL。
}

/**
* 配置创建一个 Servlet 过滤器,称为 springSecurityFilterChain 负责应用程序内的所有安全性
* (保护应用程序 URL,验证提交的用户名和密码,重定向到登录表单等)
* @return
*/
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();

return new InMemoryUserDetailsManager(user);
}
}

Spring Security 还有许多设置,想了解可以查看 WebSecurityConfig 更多常用设置
如需了解全部请查看官方文档

运行

通过项目 main() 方法主入口启动项目,应用程序启动后,将浏览器指向 http://localhost:8080
你应该看到主页:

点击超链接,访问 hello 页面,因为刚才使用 Security 设置了权限,所以访问不到,直接跳转到登录页面

输入错误的用户名密码,请重新输入登录

登录成功,点击 Sign Out 按钮可注销登录

成功注销,回到登录页面

参考

Spring 官方案例