2.12 RememberMe功能实现
Spring Security 中Remember Me为“记住我” 功能,用户只需要在登录时添加 remember me 复选框,取值为 true Spring Security会自动把用户信息存储到数据源中,以后就可以不登录进行访问。
添加依赖
Spring Security 实 现 Remember Me 功 能 时 底 层 实 现 依 赖Spring-JDBC,所以需要导入 SpringJDBC。以后多使用 MyBatis 框架而很少直接导入 spring-jdbc,所以此处导入 mybatis 启动器同时还需 要添加 MySQL 驱动
<!-- mybatis 依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!-- mysql 数据库依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
配置数据源
在 application.properties 中配置数据源。请确保数据库中已经存在shop数据库
spring.datasource.driver-class-name= com.mysql.cj.jdbc.Driver
spring.datasource.url= jdbc:mysql://localhost:3306/security?
useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username= root
spring.datasource.password= root
编写配置
RememberMeConfig.java
package com.xxxx.springsecuritydemo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
/**
* @author zhoubin
* @since 1.0.0
*/
@Configuration
public class RememberMeConfig {
@Autowired
private DataSource dataSource;
@Bean
public PersistentTokenRepository getPersistentTokenRepository(){
JdbcTokenRepositoryImpl jdbcTokenRepository = new
JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//自动建表,第一次启动时需要,第二次启动时注释掉
jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
}
修改SecurityConfig.java
在SecurityConfig中添加RememberMeConfig和UserDetailsService实现类对象,并自动注入。 在 configure 中添加下面配置内容。
http.rememberMe()
//登录逻辑交给哪个对象
.userDetailsService(userService)
// 持久层对象
.tokenRepository(persistentTokenRepository);
在客户端页面添加复选框
在客户端登录页面中添加 remember-me 的复选框,只要用户勾选了复选框下次就不需要进行登录了。
<form action="/login" method="post">
用户名:<input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
<input type="checkbox" name="remember-me" value="true"/><br/>
<input type="submit" value="登录" />
</form>
有效时间
启项目后登录状态失效了。但是可以通过设置状态有效时间,即使项目重新启动下次也可 以正常登录。
http.rememberMe()
//失效时间,单位秒
.tokenValiditySeconds(120)
//登录逻辑交给哪个对象
.userDetailsService(userService)
// 持久层对象
.tokenRepository(persistentTokenRepository);
2.13 退出登录
用户只需要向 Spring Security 项目中发送 /logout 退出请求即可。
实现退出非常简单,只要在页面中添加 /logout 的超链接即可。
<a href="/logout">退出登录</a>
为了实现更好的效果,通常添加退出的配置。默认的退出 url 为 /logout ,退出成功后跳转到 /login? logout
如果不希望使用默认值,可以通过下面的方法进行修改。
http.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login.html");
2.14 SpringSecurity中的CSRF
从刚开始学习Spring Security时,在配置类中一直存在这样一行代码: http.csrf().disable(); 如 果没有这行代码导致用户无法被认证。这行代码的含义是:关闭 csrf 防护。
什么是CSRF
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“OneClick Attack” 或者 Session Riding。通过伪造用户请求访问受信任站点的非法请求访问。 跨域:只要网络协议,ip 地址,端口中任何一个不相同就是跨域请求。 客户端与服务进行交互时,由于 http 协议本身是无状态协议,所以引入了cookie进行记录客户端身 份。在cookie中会存放session id用来识别客户端身份的。在跨域的情况下,session id 可能被第三方 恶意劫持,通过这个 session id 向服务端发起请求时,服务端会认为这个请求是合法的,可能发生很多 意想不到的事情。
2、Spring Security中的CSRF
从 Spring Security4开始CSRF防护默认开启。默认会拦截请求。进行CSRF处理。CSRF为了保证不是 其他第三方网站访问,要求访问时携带参数名为 _csrf 值为token(token 在服务端产生)的内容,如果 token和服务端的token匹配成功,则正常访问。
2.1、编写控制器方法
编写控制器方法,跳转到 templates 中 login.html 页面。
@RequestMapping("/showLogin")
public String showLogin(){
return "login";
}
2.2、新建login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
<input type="hidden" th:value="${_csrf.token}" name="_csrf"
th:if="${_csrf}"/>
用户名:<input type="text" name="username" /><br/>
密码:<input type="password" name="password" /><br/>
<input type="submit" value="登录" />
</form>
</body>
</html>
修改配置类
在配置类中注释掉 CSRF 防护失效
//关闭csrf防护
// http.csrf().disable();