1.spring security 基本介绍
相对于Apache Shiro,Spring Security提供了更多的诸如 LDAP 、 OAuth2.0 、 ACL 、 Kerberos 、
SAML 、 SSO 、 OpenID 等诸多的安全认证、鉴权协议,可以按需引用。对认证/鉴权更加灵活,粒度更
细。可以结合你自己的业务场景进行更加合理的定制化开发。在最新的Spring Security 5.x中更是提供了
响应式应用(reactive application)提供了安全控制支持。从语言上来讲,支持使用kotlin、groovy进行开
发。
Spring Security因为是利用了Spring IOC 和AOP的特性而无法脱离Spring独立存在。而Apache Shiro可以独
立存在。但是Java Web领域Spring可以说是事实上的J2EE规范。使用Java技术栈很少能脱离Spring
2. Spring Boot 集成 Spring Security基于内存用户支持
加入依赖:
<dependencies>
<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.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<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>
</dependencies>
2.1 编写配置类
SecurityConfig继承WebSecurityConfigurerAdapter
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorize -> authorize
.antMatchers("/css/**", "/index").permitAll()
.antMatchers("/user/**").hasRole("USER")
)
// 表单登录
.formLogin(formLogin -> formLogin
// 登录请求路径
.loginPage("/login")
.failureUrl("/login-error")
);
}
@Override
@Bean
public UserDetailsService userDetailsService() {
UserDetails userDetails = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(userDetails);
}
}
controller:
@Controller
public class MainController {
@RequestMapping("/")
public String root() {
return "redirect:/index";
}
@RequestMapping("/index")
public String index() {
return "index";
}
@RequestMapping("/user/index")
public String userIndex() {
return "user/index";
}
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/login-error")
public String loginError(Model model) {
model.addAttribute("loginError", true);
return "login";
}
}
静态文件:
login.html页面:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<title>Login page</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<h1>Login page</h1>
<p>Example user: user / password</p>
<p th:if="${loginError}" class="error">Wrong user or password</p>
<form th:action="@{/login}" method="post">
<label for="username">Username</label>:
<input type="text" id="username" name="username" autofocus="autofocus" /> <br />
<label for="password">Password</label>:
<input type="password" id="password" name="password" /> <br />
<input type="submit" value="Log in" />
</form>
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
</body>
</html>
index.html页面:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<title>Hello Spring Security</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div th:fragment="logout" class="logout" sec:authorize="isAuthenticated()">
Logged in user: <span sec:authentication="name"></span> |
Roles: <span sec:authentication="principal.authorities"></span>
<div>
<form action="#" th:action="@{/logout}" method="post">
<input type="submit" value="Logout" />
</form>
</div>
</div>
<h1>Hello Spring Security</h1>
<p>This is an unsecured page, but you can access the secured pages after authenticating.</p>
<ul>
<li>Go to the <a href="/user/index" th:href="@{/user/index}">secured pages</a></li>
</ul>
</body>
</html>
user/index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<title>Hello Spring Security</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div th:substituteby="index::logout"></div>
<h1>This is a secured page!</h1>
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
</body>
</html>
启动服务:
UserDetailsService
spring security支持各种数据源用户包括内存,数据库等它们被抽象成一个UserDetailsService接口,实现了UserDetailsService接口的对象可以作为认证数据源InMemoryUserDetailsManager
3.URI中的 Ant 风格
Ant 风格就是一种路径匹配表达式。主要用来对 uri 的匹配。其实跟正则表达式作用是一样
的,只不过正则表达式适用面更加宽泛, Ant 仅仅用于路径匹配。
Ant 中的通配符有三种:
?
匹配任何单字符
*
匹配0或者任意数量的 字符
**
匹配0或者更多的 目录
这里注意了单个 * 是在一个目录内进行匹配。 而 ** 是可以匹配多个目录
通配
符
示例 说明
4.WebSecurityConfigurerAdapter中常见方法
4.1 认证管理器配置方法
void configure(AuthenticationManagerBuilder auth) 用来配置认证管理器
AuthenticationManager 。说白了就是所有 UserDetails 相关的它都管,包含 PasswordEncoder
密码机。
4.2 核心过滤器配置方法
void configure(WebSecurity web) 用来配置 WebSecurity 。而 WebSecurity 是基于
Servlet Filter 用来配置 springSecurityFilterChain 。而 springSecurityFilterChain 又
被委托给了 Spring Security 核心过滤器 Bean DelegatingFilterProxy 。 相关逻辑你可以在
WebSecurityConfiguration 中找到。我们一般不会过多来自定义 WebSecurity , 使用较多的使其
ignoring() 方法用来忽略 Spring Security 对静态资源的控制。
4.3 安全过滤器链配置方法
void configure(HttpSecurity http) 这个是我们使用最多的,用来配置 HttpSecurity 。
HttpSecurity 用于构建一个安全过滤器链 SecurityFilterChain 。 SecurityFilterChain 最终
被注入核心过滤器 。 HttpSecurity 有许多我们需要的配置。我们可以通过它来进行自定义安全访问
策略
4.4 FormLoginConfigurer
该类是 form 表单登录的配置类。它提供了一些我们常用的配置方法:
loginPage(String loginPage) : 登录 页面而并不是接口,对于前后分离模式需要我们进行改
造 默认为 /login 。
loginProcessingUrl(String loginProcessingUrl) 实际表单向后台提交用户信息的
Action ,再由过滤器 UsernamePasswordAuthenticationFilter 拦截处理,该 Action 其实
不会处理任何逻辑。
usernameParameter(String usernameParameter) 用来自定义用户参数名,默认 username
。
passwordParameter(String passwordParameter) 用来自定义用户密码名,默认 password
failureUrl(String authenticationFailureUrl) 登录失败后会重定向到此路径, 一般前后
分离不会使用它。
failureForwardUrl(String forwardUrl) 登录失败会转发到此, 一般前后分离用到它。 可定
义一个 Controller (控制器)来处理返回值,但是要注意 RequestMethod 。
defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse) 默认登陆成功后
跳转到此 ,如果 alwaysUse 为 true 只要进行认证流程而且成功,会一直跳转到此。一般推荐
默认值 false
successForwardUrl(String forwardUrl) 效果等同于上面 defaultSuccessUrl 的
alwaysUse 为 true 但是要注意 RequestMethod 。
successHandler(AuthenticationSuccessHandler successHandler) 自定义认证成功处理
器,可替代上面所有的 success 方式
failureHandler(AuthenticationFailureHandler authenticationFailureHandler) 自定
义失败处理器,可替代上面所有的 failure 方式
permitAll(boolean permitAll) form 表单登录是否放开
5.HttpSecurity常见方法