SpringSecurity学习记录4

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

image-20210102100401846

如果不希望使用默认值,可以通过下面的方法进行修改。

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();

猜你喜欢

转载自blog.csdn.net/zhanduo0118/article/details/112093807