Spring Security 是针对 Spring 项目的安全框架,也是 Spring Boot 底层安全模块默认的技术选型。它能够实现强大的 Web 安全控制。对于安全控制吧,咱们仅如引入 Security 场景启动器,进行少许配置,便可实现强大的安全管理。html
应用程序安全的主要两个区域就是“认证”和“受权”:html5
SpringSecurity with Boot 快速开始 | SpringSecurity 官方文档java
一、使用 maven 新建 SpringBoot 项目,引入 Web、Thymeleaf、Security 场景启动器,依赖以下:web
<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.19.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>zze.spring</groupId> <artifactId>security</artifactId> <version>0.0.1-SNAPSHOT</version> <name>security</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <!--修改 thymeleaf 依赖版本为 3 --> <thymeleaf.version>3.0.11.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.4.1</thymeleaf-layout-dialect.version> <thymeleaf-extras-springsecurity4.version>3.0.2.RELEASE</thymeleaf-extras-springsecurity4.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <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.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <!--thymeleaf 模板中使用 springsecurity 标签--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
二、编写测试模板页:spring
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <div sec:authorize="!isAuthenticated()"> <a th:href="@{/login}">请登陆</a> </div> <div sec:authorize="isAuthenticated()"> <span sec:authentication="name"/> 您好,您拥有角色:<span sec:authentication="principal.authorities"/> <form th:action="@{/logout}" method="post"> <input type="submit" value="注销"> </form> </div> <div sec:authorize="hasRole('VIP1')"><a th:href="@{/level/1}">LEVEL 1</a></div> <div sec:authorize="hasRole('VIP2')"><a th:href="@{/level/2}">LEVEL 2</a></div> <div sec:authorize="hasRole('VIP3')"><a th:href="@{/level/3}">LEVEL 3</a></div> </body> </html>
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>登陆页</title> </head> <body> <form th:action="@{/login}" method="post" > 用户名:<input type="text" name="username"> <br> 密码:<input type="text" name="password"> <br> <input type="checkbox" name="rememberMe"> <input type="submit" value="登陆"/> </form> </body> </html>
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>级别</title> </head> <body> <a th:href="@{/}">首页</a> <h1 th:text="${level}"></h1> </body> </html>
三、编写测试 Controller:apache
package zze.spring.security.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @Controller public class TestController { private final String PREFIX = "pages/"; // 欢迎页 @GetMapping("/") public String index() { return "welcome"; } @GetMapping("/level/{level}") public String level(@PathVariable Integer level, Model model) { model.addAttribute("level", level == 1 ? "初级" : level == 2 ? "中级" : "高级"); return PREFIX + "level"; } @GetMapping("/login") public String login(){ return "login"; } }
四、配置:浏览器
package zze.spring.security.config; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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; /** * 编写配置类继承 WebSecurityConfigurerAdapter */ @EnableWebSecurity // 启用 WebSecurity 模式 public class SecurityConfig extends WebSecurityConfigurerAdapter { /** * 控制请求的访问权限 */ @Override protected void configure(HttpSecurity http) throws Exception { // super.configure(http); // 定制请求的受权规则 http.authorizeRequests().antMatchers("/").permitAll() // "/" 容许任何人访问 .antMatchers("/level/1").hasRole("VIP1") // "/level/1" 仅容许拥有角色 VIP1 的主体访问 .antMatchers("/level/2").hasRole("VIP2") // "/level/2" 仅容许拥有角色 VIP2 的主体访问 .antMatchers("/level/3").hasRole("VIP3"); // "/level/3" 仅容许拥有角色 VIP3 的主体访问 // 开启自动配置的登陆功能,开启后未登陆状态访问将会自动重定向到 /login 登陆页 // 一、访问 /login 来到登陆页 // 二、重定向到 /login?error 表示登陆失败 // 三、可经过 loginPage() 方法修改使用本身的登陆页,登陆请求须要为 post,的用户名参数默认为 username ,密码参数为 password 。 // 四、若是使用了 loginPage() 方法修改了登陆页,那么该请求的 post 方式就是登陆请求。好比修改 /userLogin 为登陆页,那么 post 请求 /userLogin 则是登陆操做 http.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login"); // 开启自动配置的注销 // 一、访问 /logout 表示用户注销,状况 session // 二、注销成功默认会重定向到 /login?logout // // 经过 logoutSuccessUrl("/") 方法指定注销成功重定向的页面 http.logout().logoutSuccessUrl("/"); // 开启记住我功能 // 一、登陆成功后,将 cookie 发送给浏览器保存,之后访问都会带上这个 cookie,经过检查就能够免登陆 // 二、点击注销会删除 cookie // 三、可经过 rememberMeParameter 方法定义登陆操做的记住我参数名 http.rememberMe().rememberMeParameter("rememberMe"); } // 定义认证规则 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // super.configure(auth); auth.inMemoryAuthentication().withUser("zhangsan").password("123456").roles("VIP1", "VIP2") // 内存中存入一个用户(主体),用户名为 zhangsan 密码为 123456,拥有角色 VIP1 和 VIP2 .and() .withUser("lisi").password("123456").roles("VIP2", "VIP3") // 内存中存入一个用户(主体),用户名为 lisi 密码为 123456,拥有角色 VIP2 和 VIP3 .and() .withUser("wangwu").password("123456").roles("VIP1", "VIP3"); // 内存中存入一个用户(主体),用户名为 wangwu 密码为 123456,拥有角色 VIP1 和 VIP3 } }