用户登录实现说明
- 用户登录后,就把用户名和uuid保存分别作为key和value保存到cookie里,把cookie中的value作为redis的key去获取redis的value,如果不存在,或者数据对比不一致再去读取数据库有没有对应的数据,还是没有的话,就提示用户名或密码有误
项目目录:
核心代码:
PersonController类
package com.cfay.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.cfay.pojo.Person;
import com.cfay.service.PersonService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import redis.clients.jedis.Jedis;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
/**
* 实现:用户的登录
* 用户登录后,就把登录信息保存到redis中,下次登录就从redis中读取,
* 没有的话再去读取数据库有没有对应的数据,还是没有的话,就提示用户名或密码有误
*/
@Controller
@Slf4j
public class PersonController {
// slf4j日志记录器
private static final Logger logger = LoggerFactory.getLogger(PersonController.class.getName());
public static final String CACHE_KEY_PERSON = "person";
@Autowired
private PersonService personService;
Jedis jedis = new Jedis();
@GetMapping("/login")
public String toLogin() {
return "login";
}
@PostMapping("/login")
public String toMain(Person person, Model model, HttpServletRequest req, HttpServletResponse rep, HttpSession session) {
String cookieVal = null;
String redisVal = null;
model.addAttribute("name", person.getName());
Cookie[] cookies = req.getCookies();
//cookies是否有数据
if (cookies != null && cookies.length != 0) {
for (Cookie cookie : cookies) {
//cookie的key跟当前用户是否一致,是的话就获取对应的cookie值
if (cookie.getName().equals(CACHE_KEY_PERSON + person.getName())) {
cookieVal = cookie.getValue();
}
}
}
//先去redis查是否有这个信息,如果没有,再去数据库中查
if (StringUtils.isNotEmpty(cookieVal)) {
redisVal = jedis.get(cookieVal);
}
//redis存在这个key
if (StringUtils.isNotEmpty(redisVal)) {
//判断信息是否一致
//把string类型的json数据变为json对象
JSONObject jsonObject = JSONObject.parseObject(redisVal);
//把json对象变为pojo对象
Person person1 = jsonObject.toJavaObject(Person.class);
if (person.getName().equals(person1.getName()) && person.getPassword().equals(person1.getPassword())) {
//登录成功,跳转到首页或指定的页面
logger.info("=============使用redis登录=================");
return "main";
} else {
//信息有误
model.addAttribute("msg", "密码有误,请重新输入!");
//去数据库中查询用户的最新信息
logger.info("=============redis中的信息过时了!!!=================");
return loginVerification(model, person, rep, session);
}
} else {
//redis中不存在这个信息,去数据库中查询信息
return loginVerification(model, person, rep, session);
}
}
public String loginVerification(Model model, Person person, HttpServletResponse rep, HttpSession session) {
//生成uuid并去掉中间的-
String uuid = UUID.randomUUID().toString().replace("-","");
//去数据库中查询是否存在用户信息
HashMap<String, Object> map = new HashMap<>();
map.put("name", person.getName());
map.put("password", person.getPassword());
List<Person> p1 = personService.getBaseMapper().selectByMap(map);
if (CollectionUtils.isEmpty(p1)) {
//不存在,提示用户名或密码有误
model.addAttribute("msg", "用户名或密码有误");
logger.info("=============用户名或密码有误" + person.getName() + "," + person.getPassword() + "=================");
return "login";
} else {
//登录成功
person = p1.get(0);
//把登录信息保存到redis中
Cookie cookie = new Cookie(CACHE_KEY_PERSON + person.getName(), CACHE_KEY_PERSON + uuid);
rep.addCookie(cookie);
session.setAttribute("person", person);
//60秒中有效
jedis.setex(CACHE_KEY_PERSON + uuid, 60, JSON.toJSONString(person));
logger.info("=============登录信息保存到redis中=================");
return "main";
}
}
}
WebConfig配置类
package com.cfay.config;
import com.cfay.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 用页面和地址做一个映射关系来实现页面跳转
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 跳转方式为:转发; 第一个参数为路径, 第二个参数为视图路径名称
registry.addViewController("/index").setViewName("index");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/main").setViewName("main");
}
/**
* 配置拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
// 被拦截路径
.addPathPatterns("/**")
// 忽略路径, 通常我们需要忽略掉一些静态资源
.excludePathPatterns("/login", "/**/**.js", "/**/*.css", "/**/*.png ", "/**/*.jpg", "/**/*.gif ");
}
}
LoginInterceptor登录拦截器
package com.cfay.interceptor;
import com.cfay.pojo.Person;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashSet;
import java.util.Set;
/**
* 登录验证拦截
*/
@Slf4j
public class LoginInterceptor extends HandlerInterceptorAdapter {
// slf4j日志记录器
private static final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class.getName());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String basePath = request.getContextPath();
String path = request.getRequestURI();
if (!doLoginInterceptor(path, basePath)) {//是否进行登陆拦截
return true;
}
HttpSession session = request.getSession();
Person personMsg = (Person) session.getAttribute("person");
if (personMsg == null) {
logger.info("===请先进行登录===");
// 未登录,拦截到登录页面
request.getRequestDispatcher("/login").forward(request, response);
return false;
}
logger.info("登录用户为=" + personMsg.getName());
request.setAttribute("name", personMsg.getName());
return true;
}
/**
* 是否进行登陆过滤
*
* @param path
* @param basePath
* @return
*/
private boolean doLoginInterceptor(String path, String basePath) {
path = path.substring(basePath.length());
Set<String> releasePaths = new HashSet<>();
//设置不进行登录拦截的路径
releasePaths.add("/index");
releasePaths.add("/login");
if (releasePaths.contains(path)) {
return false;
}
return true;
}
}
application.properties文件
# 应用服务 WEB 访问端口
server.port=8080
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=123456
# THYMELEAF (ThymeleafAutoConfiguration)
# 开启模板缓存(默认值: true )
spring.thymeleaf.cache=false
# 检查模板是否存在,然后再呈现
spring.thymeleaf.check-template=true
# 检查模板位置是否正确(默认值 :true )
spring.thymeleaf.check-template-location=true
#Content-Type 的值(默认值: text/html )
spring.thymeleaf.content-type=text/html
# 开启 MVC Thymeleaf 视图解析(默认值: true )
spring.thymeleaf.enabled=true
# 模板编码
spring.thymeleaf.encoding=UTF-8
# 在构建 URL 时添加到视图名称前的前缀(默认值: classpath:/templates/ )
spring.thymeleaf.prefix=classpath:/templates/
# 在构建 URL 时添加到视图名称后的后缀(默认值: .html )
spring.thymeleaf.suffix=.html
#redis的配置
spring.redis.database=0
#redis服务器地址
spring.redis.host=localhost
#redis服务器连接端口
spring.redis.port=6379
#redis服务器连接密码(默认为空)
spring.redis.password=
#启用驼峰
mybatis.configuration.map-underscore-to-camel-case=true
pom文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cfay</groupId>
<artifactId>springboot08</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot08</name>
<description>redis实现登录功能</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</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>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<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>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.cfay.Springboot08Application</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
原码已放在阿里云上,参考可以看:https://code.aliyun.com/lichubin/springboot-redis.git