zoukankan      html  css  js  c++  java
  • springboot结合redis使用token实现登录注销功能

    实现思路

    • 用户在未登录状态下通过路径访问项目,显示未登录
    • 用户通过账号密码登录后,返回token值
    • 登录后,可以通过路径访问项目
    • 没有在Headers中添加token时,无法注销;添加了token后,可以成功注销用户

    项目结构

    添加redis依赖

    <?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.example</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>demo</name>
        <description>Demo project for Spring Boot</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-web</artifactId>
            </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>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </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.example.demo.DemoApplication</mainClass>
                    </configuration>
                    <executions>
                        <execution>
                            <id>repackage</id>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    

    配置redis信息和服务器端口号

    server:
      port: 8083
    
    spring:
      redis:
        host: localhost
        port: 6379
        database: 5
    

    实现redis操作代码:添加、获取、删除

    package com.example.demo.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    import org.springframework.stereotype.Service;
    
    @Service
    public class RedisService {
    
        @Autowired
        RedisTemplate redisTemplate;
    
        public void set(String key,Object value){
            //更改在redis里面查看key编码问题
            RedisSerializer redisSerializer = new StringRedisSerializer();
            redisTemplate.setKeySerializer(redisSerializer);
            ValueOperations<String,Object> vo = redisTemplate.opsForValue();
            vo.set(key,value);
        }
    
        public Object get(String key){
            ValueOperations<String,Object> vo = redisTemplate.opsForValue();
            return vo.get(key);
        }
    
        public boolean delete(String key){
            return redisTemplate.delete(key);
        }
    
    }
    
    

    实现登录和注销功能代码

    package com.example.demo.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.UUID;
    
    @Service
    public class LoginService {
    
        @Autowired
        RedisService redisService;
    
        /**
         * 进行登录操作,如果用户名和密码正确,使用UUID一个字符串作为token
         * @param username
         * @param password
         * @return
         */
        public String login(String username,String password){
            if(username.equals("liu")&&password.equals("123")){
                String token = UUID.randomUUID().toString();
                redisService.set(token,username);
                return username+"登录成功,token是:"+token;
            }else {
                return "用户名或密码错误";
            }
    
        }
    
        /**
         * 进行注销操作,实质是删除redis和token中的缓存
         * @param httpServletRequest
         * @return
         */
        public String logout(HttpServletRequest httpServletRequest){
            String token = httpServletRequest.getHeader("token");
            boolean delete = redisService.delete(token);
            if (delete){
                return "注销成功";
            }else {
                return "注销失败";
            }
        }
    
    
    }
    
    

    针对登录和注销功能实现Controller方便后面调用

    package com.example.demo.controller;
    
    import com.example.demo.service.LoginService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * 在controller中对登录和注销方法进行调用
     */
    @RestController
    @RequestMapping("/login")
    public class LoginController {
    
        @Autowired
        LoginService loginService;
    
        @RequestMapping("/login")
        public String login(String username, String password) {
            return loginService.login(username, password);
        }
    
        @RequestMapping("/logout")
        public String logout(HttpServletRequest httpServletRequest) {
            return loginService.logout(httpServletRequest);
        }
    
    
    }
    
    

    再写一个测试的Controller类,用来测试用户没登录的时候,通过路径无法访问

    package com.example.demo.controller;
    
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/test")
    public class TestController {
    
        @RequestMapping("test")
        public String test(){
            return "test";
        }
    
    }
    
    

    实现一个拦截器,对用户登录状态进行判断

    package com.example.demo.interceptor;
    
    import com.example.demo.service.RedisService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Objects;
    
    /**
     * 拦截器中需要取出header中的token,然后去redis中进行判断,如果存在,则允许操作,则返回提示信息
     */
    @Component
    public class AuthInterceptor implements HandlerInterceptor {
    
        @Autowired
        RedisService redisService;
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            String token = request.getHeader("token");
            if (StringUtils.isEmpty(token)) {
                response.getWriter().print("用户未登录");
                return false;
            }
    
            Object loginStatues = redisService.get(token);
            if (Objects.isNull(loginStatues)) {
                response.getWriter().print("token错误");
                return false;
            }
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
        }
    }
    
    

    配置拦截器

    package com.example.demo.config;
    
    import com.example.demo.interceptor.AuthInterceptor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Configurable;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class AuthConfig implements WebMvcConfigurer {
    
        @Autowired
        AuthInterceptor authInterceptor;
    
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(authInterceptor).addPathPatterns("/test/**").excludePathPatterns("/login/**");
        }
    }
    
    

    源码

    https://github.com/Wranglery/springboot_redis_token_login/tree/main/springboot_redis_token_login

  • 相关阅读:
    为何与0xff进行与运算
    智能指针学习笔记
    linux下多线程编程
    redis源码分析之内存布局
    spring
    java
    程序员进修之路
    散列类型(hash)
    字符串类型
    Jmeter使用Websocket插件测试SingalR,外加还有阿里云PTS的Jmeter原生测试爬坑日志。
  • 原文地址:https://www.cnblogs.com/lyd447113735/p/14890546.html
Copyright © 2011-2022 走看看