springboot+redis+mybatis plug实现用户的简单登录

该博客介绍了一个Spring Boot应用中如何利用Redis进行用户登录验证的实现。当用户登录时,用户名和uuid存储在cookie中,并在Redis中进行信息匹配。如果Redis中信息不一致或不存在,则会查询数据库。登录成功后,信息会被保存到Redis,同时使用拦截器进行登录状态检查。
摘要由CSDN通过智能技术生成

用户登录实现说明

  • 用户登录后,就把用户名和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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楚风岸影

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值