开篇一张图,道理全靠悟。

示例如下:

1.    新建Maven项目  remember_me

2.   pom.xml

<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.java</groupId>
<artifactId>remember_me</artifactId>
<version>1.0.0</version> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent> <dependencies> <!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.0.0.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.11</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency> <!-- 热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.8.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>provided</scope>
</dependency> </dependencies> <build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin> <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

3.   RememberMeStarter.java

package com.java;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; /**
* <blockquote><pre>
*
* 主启动类
*
* </pre></blockquote>
*
* @author Logan
*
*/
@SpringBootApplication
public class RememberMeStarter { public static void main(String[] args) {
SpringApplication.run(RememberMeStarter.class, args);
} }

4.   ApplicationContextConfig.java

package com.java.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* 配置文件类
*
* @author Logan
*
*/
@Configuration
public class ApplicationContextConfig { /**
* <blockquote><pre>
*
* 配置密码编码器,Spring Security 5.X必须配置,否则登录时报空指针异常
*
* </pre></blockquote>
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
} }

5.   RepositoryConfig.java

package com.java.config;

import javax.sql.DataSource;

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; /**
* 数据库相关配置
*
* @author Logan
*
*/
@Configuration
public class RepositoryConfig { @Bean
public PersistentTokenRepository tokenRepository(DataSource dataSource) {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
// tokenRepository.setCreateTableOnStartup(true); // 第一次启动时可使用此功能自动创建表,第二次要关闭,否则表已存在会启动报错
return tokenRepository;
} }

6.   SecurityUserDetailsService.java

package com.java.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component; /**
* UserDetailsService实现类
*
* @author Logan
*
*/
@Component
public class SecurityUserDetailsService implements UserDetailsService { @Autowired
private PasswordEncoder passwordEncoder; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 数据库存储密码为加密后的密文(明文为123456)
String password = passwordEncoder.encode("123456"); System.out.println("username: " + username);
System.out.println("password: " + password); // 模拟查询数据库,获取属于Admin和Normal角色的用户
User user = new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("Admin,Normal")); return user;
} }

7.   LoginConfig.java

package com.java.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; /**
* 登录相关配置
*
* @author Logan
*
*/
@Configuration
public class LoginConfig extends WebSecurityConfigurerAdapter { @Autowired
private PersistentTokenRepository tokenRepository; @Autowired
private UserDetailsService userDetailsService; @Override
protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 设置不需要授权的请求
.antMatchers("/js/*", "/login.html").permitAll() // 其它任何请求都需要验证权限
.anyRequest().authenticated() // 设置自定义表单登录页面
.and().formLogin().loginPage("/login.html") // 设置登录验证请求地址为自定义登录页配置action ("/login/form")
.loginProcessingUrl("/login/form") // 设置默认登录成功跳转页面
.defaultSuccessUrl("/main.html") // 添加记住我功能
.and().rememberMe().tokenRepository(tokenRepository) // 有效期为两周
.tokenValiditySeconds(3600 * 24 * 14) // 设置UserDetailsService
.userDetailsService(userDetailsService) // 暂时停用csrf,否则会影响验证
.and().csrf().disable();
} }

8.  src/main/resources  下文件如下

9.   application.properties

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.32.10:3306/security?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

10.   login.html

<!DOCTYPE html>
<html> <head>
<title>登录</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
</head> <body> <!--登录框-->
<div align="center">
<h2>用户自定义登录页面</h2>
<fieldset style="width: 300px;">
<legend>登录框</legend>
<form action="/login/form" method="post">
<table>
<tr>
<th>用户名:</th>
<td><input name="username" /> </td>
</tr>
<tr>
<th>密码:</th>
<td><input type="password" name="password" /> </td>
</tr>
<tr>
<th>记住我:</th>
<td><input type="checkbox" name="remember-me" value="true" checked="checked" /></td>
</tr>
<tr>
<th></th>
<td></td>
</tr>
<tr>
<td colspan="2" align="center"><button type="submit">登录</button></td>
</tr>
</table>
</form>
</fieldset> </div> </body> </html>

11.   main.html

<!DOCTYPE html>
<html> <head>
<title>首页</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
<script>
function getHostMessage() {
$.ajax({
type: "get",
url: "/getHostMessage",
async: true,
success: function(data) {
$("#msg").val(JSON.stringify(data));
}
});
}
</script>
</head> <body> <div>
<h2>首页</h2>
<table>
<tr>
<td><button onclick="getHostMessage()">获取主机信息</button></td>
</tr>
</table> </div> <!--响应内容-->
<div>
<textarea id="msg" style="width: 800px;height: 800px;"></textarea>
</div> </body> </html>

12.   js/jquery-3.3.1.min.js 可在官网下载

https://code.jquery.com/jquery-3.3.1.min.js

13.   创建数据库

DROP DATABASE IF EXISTS security;
CREATE DATABASE security;
USE security;
create table persistent_logins (
username varchar(64) not null,
series varchar(64) primary key,
token varchar(64) not null,
last_used timestamp not null
);

14.   运行 RememberMeStarter.java , 启动测试

浏览器输入首页  http://localhost:8080/main.html

地址栏自动跳转到登录页面,如下:

输入如下信息:

User:Logan

Password:123456

单击【登录】按钮,自动跳转到首页。

观察数据库,此时自动生成一条记录,username字段值为登录时使用用户名,记住我Token信息已生成。

如下所示:

测试【记住我】 功能是否生效

关闭浏览器重新打开,或者关闭系统重新启动,再次访问首页,页面不再跳转到登录页,直接显示首页信息。

如下所示:

.

Spring Security 实现记住我的更多相关文章

  1. spring security实现记住我下次自动登录功能

    目录 spring security实现记住我下次自动登录功能 一.原理分析 二.实现方式 2.1 简单实现方式 2.2 数据库实现方式 三.区分是密码登录还是rememberme登录 spring ...

  2. spring security实现记录用户登录时间等信息

    目录 spring security实现记录用户登录时间等信息 一.原理分析 二.实现方式 2.1 自定义AuthenticationSuccessHandler实现类 2.2 在spring-sec ...

  3. Spring Security构建Rest服务-0900-rememberMe记住我

    Spring security记住我基本原理: 登录的时候,请求发送给过滤器UsernamePasswordAuthenticationFilter,当该过滤器认证成功后,会调用RememberMeS ...

  4. Spring Security框架下实现两周内自动登录"记住我"功能

    本文是Spring Security系列中的一篇.在上一篇文章中,我们通过实现UserDetailsService和UserDetails接口,实现了动态的从数据库加载用户.角色.权限相关信息,从而实 ...

  5. spring security remember me实现自动登录

    1 默认策略 在我们自定义的login中增加一个选择框 <input type="submit" value="Login" /> <br/& ...

  6. 第一章 Spring Security是什么?

    1. 介绍 1.1 Spring Security是什么? Spring Security是一个强大的和高度可定制的身份验证和访问控制框架. 它是保证基于spring的应用程序安全的实际标准. 1.2 ...

  7. 使用 Spring Security 保护 Web 应用的安全

    安全一直是 Web 应用开发中非常重要的一个方面.从安全的角度来说,需要考虑用户认证和授权两个方面.为 Web 应用增加安全方面的能力并非一件简单的事情,需要考虑不同的认证和授权机制.Spring S ...

  8. 【Spring】关于Boot应用中集成Spring Security你必须了解的那些事

    Spring Security Spring Security是Spring社区的一个顶级项目,也是Spring Boot官方推荐使用的Security框架.除了常规的Authentication和A ...

  9. Spring Security 入门详解(转)

    1.Spring Security介绍 Spring Security是基于spring的应用程序提供声明式安全保护的安全性框架,它提供了完整的安全性解决方案,能够在web请求级别和方法调用级别 处理 ...

随机推荐

  1. java——哈希表 HashTable

    在一个类中重写hashCode()和equals() package Date_pacage.hash; public class Student { private int grade; priva ...

  2. team foundation server 工具的使用

    1.打开TFS工具点击创建集合,填写集合名称,下一步,按照步骤一步一步的往下操作. 2.创建完集合以后,打开VS工具,如下图,在主页上左键选择新建团队项目. 3.选择团队项目,然后选择新建的项目集合和 ...

  3. jQuery源码解读 --- 整体架构

    最近学习比较忙,感觉想要提高还是要读源码,所以准备考试这个考试结束就开始读jquery源码啦,加油~

  4. Kudu安装(官网推荐的步骤)(installing build Kudu from source)

    不多说,直接上干货! Kudu安装前的建议说明(博主推荐) 这是安装Kudu的另一种方法 Kudu安装(官网推荐的步骤)(installing Kudu using parcels or packag ...

  5. Jquery load()加载GB2312页面时出现乱码的解决方法

    问题描述:jquery的字符集是utf-8,load方法加载完GB2312编码静态页面后,出现中文乱码. a.php <script language="javascript" ...

  6. POJ 3189——Steady Cow Assignment——————【多重匹配、二分枚举区间长度】

     Steady Cow Assignment Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I ...

  7. c# 的默认访问修饰符(转)

    c# 的访问修饰符是private 还是 internal? 准确的说,不能一概而论. 类(class)或结构(struct)如果不是在其它类或结构中的话,它的访问类型要不就是internal, 要不 ...

  8. [Java][Servlet] Cannot call sendRedirect() after the response has been committed

    做一个Login Demo的时候,写了如下代码: protected void doPost(HttpServletRequest request, HttpServletResponse respo ...

  9. 粗看ES6之解构赋值

    标签: javascript es6 什么是解构赋值? 示例如下: <!DOCTYPE html> <html> <head> <meta charset=& ...

  10. centos7服务器搭建javaweb运行环境及代码部署

    之前在一直在学习java web终于写完了第一个小demo,于是在阿里云上买了一个服务器,开始了配置服务器环境的踩坑之旅.... ps:本文不讨论服务器配置的具体步骤,网上都很多,按部就班就是,本文主 ...