CRM项目基于JWT实现Token回传Json给前台登录保持并用redis储存登录信息------CRM项目

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.Alatus</groupId>
    <artifactId>NetCRM-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>NetCRM-server</name>
    <description>NetCRM-server</description>
    <properties>
        <java.version>17</java.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-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>
<!--        JWT依赖-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>4.4.0</version>
        </dependency>
<!--        热补丁依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
<!--        mysql依赖-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
<!--        lomback-->
        <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>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter-test</artifactId>
            <version>3.0.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.Alatus</groupId>
    <artifactId>NetCRM-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>NetCRM-server</name>
    <description>NetCRM-server</description>
    <properties>
        <java.version>17</java.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-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>
<!--        JWT依赖-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>4.4.0</version>
        </dependency>
<!--        热补丁依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
<!--        mysql依赖-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
<!--        lomback-->
        <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>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter-test</artifactId>
            <version>3.0.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
package com.alatus.service;

import java.util.concurrent.TimeUnit;

public interface RedisService {
    void setValue(String key,Object value);
    Object getValue(String key);
    Boolean removeValue(String key);
    Boolean expire(String key, Long timeOut, TimeUnit timeUnit);
}
package com.alatus.service;

import java.util.concurrent.TimeUnit;

public interface RedisService {
    void setValue(String key,Object value);
    Object getValue(String key);
    Boolean removeValue(String key);
    Boolean expire(String key, Long timeOut, TimeUnit timeUnit);
}
package com.alatus.service.impl;

import com.alatus.service.RedisService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class RedisServiceImpl implements RedisService {
//    数据源
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
//        放入数据
    @Override
    public void setValue(String key, Object value) {
        redisTemplate.opsForValue().set(key,value);
    }
//取出数据
    @Override
    public Object getValue(String key) {
        return redisTemplate.opsForValue().get(key);
    }
//删除数据
    @Override
    public Boolean removeValue(String key) {
        return redisTemplate.delete(key);
    }

    @Override
    public Boolean expire(String key, Long timeOut, TimeUnit timeUnit) {
        return redisTemplate.expire(key,timeOut,timeUnit);
    }
}
package com.alatus.service.impl;

import com.alatus.service.RedisService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class RedisServiceImpl implements RedisService {
//    数据源
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
//        放入数据
    @Override
    public void setValue(String key, Object value) {
        redisTemplate.opsForValue().set(key,value);
    }
//取出数据
    @Override
    public Object getValue(String key) {
        return redisTemplate.opsForValue().get(key);
    }
//删除数据
    @Override
    public Boolean removeValue(String key) {
        return redisTemplate.delete(key);
    }

    @Override
    public Boolean expire(String key, Long timeOut, TimeUnit timeUnit) {
        return redisTemplate.expire(key,timeOut,timeUnit);
    }
}
package com.alatus.constant;

public class Constants {
    public static final String LOGIN_URL = "/api/login";
//    redis的key命名规范,项目名:模块名:功能名:唯一业务参数(比如用户ID)
    public static final String REDIS_JWT_KEY = "crmSystem:user:login:";
//    七天时间
    public static final Long EXPIRE_TIME = 7 * 24 * 60 * 60L;
//    三十分钟
    public static final Long DEFAULT_EXPIRE_TIME = 30 * 60L;
}
package com.alatus.constant;

public class Constants {
    public static final String LOGIN_URL = "/api/login";
//    redis的key命名规范,项目名:模块名:功能名:唯一业务参数(比如用户ID)
    public static final String REDIS_JWT_KEY = "crmSystem:user:login:";
//    七天时间
    public static final Long EXPIRE_TIME = 7 * 24 * 60 * 60L;
//    三十分钟
    public static final Long DEFAULT_EXPIRE_TIME = 30 * 60L;
}
package com.alatus.util;

import com.alatus.model.TUser;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * jwt的工具类
 *
 */
public class JWTUtils {
    private static final String SECRET = "dYB300olWQ3345;ld<3w48";
    /**
     * 生成jwt
     *
     * @return
     */
    public static String createJWT(String userJSON) {
        //组装头数据
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");

        //链式编程
        return JWT.create()
                //头部
                .withHeader(header)

                //负载(可以有多个)
                .withClaim("user", userJSON)

                //签名
                .sign(Algorithm.HMAC256(SECRET));
    }

    /**
     * 验证jwt
     *
     */
    public static Boolean verifyJWT(String jwt) {
        try {
            // 使用密钥创建一个jwt验证器
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //jwt验证器验证jwt
            jwtVerifier.verify(jwt); //如果此行代码没有抛出异常,就说明jwt验证通过,抛出异常,就说明jwt验证不通过

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 解析jwt
     *
     */
    public static String parseJWT(String jwt) {
        Map<String, Object> map = new HashMap<>();
        try {
            // 使用密钥创建一个jwt验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //jwt验证器对象验证jwt,得到一个解码后的jwt对象
            DecodedJWT decodedJWT = jwtVerifier.verify(jwt);

            //验证通过了,就开始解析负载里面的数据
            Claim userJSON = decodedJWT.getClaim("user");

            return userJSON.asString();
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析jwt得到userId
     *
     * @param jwt
     * @return
     */
    public static Integer parseJWTByUserId(String jwt) {
        String userJSON = parseJWT(jwt);
        TUser user = JSONUtils.toBean(userJSON, TUser.class);
        return user.getId();
    }

    /**
     * 解析jwt得到userRole
     *
     * @param jwt
     * @return
     */
    public static List<String> parseJWTByUserRole(String jwt) {
        String userJSON = parseJWT(jwt);
        TUser user = JSONUtils.toBean(userJSON, TUser.class);
        return null;
    }
}
package com.alatus.util;

import com.alatus.model.TUser;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * jwt的工具类
 *
 */
public class JWTUtils {
    private static final String SECRET = "dYB300olWQ3345;ld<3w48";
    /**
     * 生成jwt
     *
     * @return
     */
    public static String createJWT(String userJSON) {
        //组装头数据
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");

        //链式编程
        return JWT.create()
                //头部
                .withHeader(header)

                //负载(可以有多个)
                .withClaim("user", userJSON)

                //签名
                .sign(Algorithm.HMAC256(SECRET));
    }

    /**
     * 验证jwt
     *
     */
    public static Boolean verifyJWT(String jwt) {
        try {
            // 使用密钥创建一个jwt验证器
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //jwt验证器验证jwt
            jwtVerifier.verify(jwt); //如果此行代码没有抛出异常,就说明jwt验证通过,抛出异常,就说明jwt验证不通过

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 解析jwt
     *
     */
    public static String parseJWT(String jwt) {
        Map<String, Object> map = new HashMap<>();
        try {
            // 使用密钥创建一个jwt验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //jwt验证器对象验证jwt,得到一个解码后的jwt对象
            DecodedJWT decodedJWT = jwtVerifier.verify(jwt);

            //验证通过了,就开始解析负载里面的数据
            Claim userJSON = decodedJWT.getClaim("user");

            return userJSON.asString();
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析jwt得到userId
     *
     * @param jwt
     * @return
     */
    public static Integer parseJWTByUserId(String jwt) {
        String userJSON = parseJWT(jwt);
        TUser user = JSONUtils.toBean(userJSON, TUser.class);
        return user.getId();
    }

    /**
     * 解析jwt得到userRole
     *
     * @param jwt
     * @return
     */
    public static List<String> parseJWTByUserRole(String jwt) {
        String userJSON = parseJWT(jwt);
        TUser user = JSONUtils.toBean(userJSON, TUser.class);
        return null;
    }
}
package com.alatus.config.handler;

import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.JWTUtils;
import com.alatus.util.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Resource
    private RedisService redisService;
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //由于禁用了session,我们在登录成功后,需要在服务器保持用户的登录状态,前端下次来访问服务器端的时候,服务器端要知道这个人登录了
        TUser tUser = (TUser) authentication.getPrincipal();
//        登录成功的统一结果
        R result = R.OK(tUser);
//        把R对象转为JSON
        String resultJSON = JSONUtils.toJSON(result);
//        生成jwt
        String jwt = JWTUtils.createJWT(resultJSON);
        String key = Constants.REDIS_JWT_KEY+tUser.getId();
//        写入Redis
        redisService.setValue(key,jwt);
//        设置jwt的过期时间,如果选择了记住我,jwt过期时间为七天,否则是30分钟
        Boolean rememberMe = Boolean.valueOf(request.getParameter("rememberMe"));
        if(rememberMe){
            redisService.expire(key,Constants.EXPIRE_TIME, TimeUnit.SECONDS);
        }
        else{
            redisService.expire(key,Constants.DEFAULT_EXPIRE_TIME,TimeUnit.SECONDS);
        }
//        把R以JSON传回前端
        ResponseUtils.write(response,jwt);
    }
}
package com.alatus.config.handler;

import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.JWTUtils;
import com.alatus.util.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Resource
    private RedisService redisService;
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //由于禁用了session,我们在登录成功后,需要在服务器保持用户的登录状态,前端下次来访问服务器端的时候,服务器端要知道这个人登录了
        TUser tUser = (TUser) authentication.getPrincipal();
//        登录成功的统一结果
        R result = R.OK(tUser);
//        把R对象转为JSON
        String resultJSON = JSONUtils.toJSON(result);
//        生成jwt
        String jwt = JWTUtils.createJWT(resultJSON);
        String key = Constants.REDIS_JWT_KEY+tUser.getId();
//        写入Redis
        redisService.setValue(key,jwt);
//        设置jwt的过期时间,如果选择了记住我,jwt过期时间为七天,否则是30分钟
        Boolean rememberMe = Boolean.valueOf(request.getParameter("rememberMe"));
        if(rememberMe){
            redisService.expire(key,Constants.EXPIRE_TIME, TimeUnit.SECONDS);
        }
        else{
            redisService.expire(key,Constants.DEFAULT_EXPIRE_TIME,TimeUnit.SECONDS);
        }
//        把R以JSON传回前端
        ResponseUtils.write(response,jwt);
    }
}

最近更新

  1. TCP协议是安全的吗?

    2024-02-08 13:40:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-08 13:40:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-08 13:40:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-08 13:40:01       18 阅读

热门阅读

  1. Python在小型无人机

    2024-02-08 13:40:01       36 阅读
  2. 【SQL高频基础题】619.只出现一次的最大数字

    2024-02-08 13:40:01       35 阅读
  3. SQL常用优化手段chi

    2024-02-08 13:40:01       35 阅读
  4. C++ bool 布尔类型

    2024-02-08 13:40:01       35 阅读
  5. 数据可视化教程!我将全程出镜解说

    2024-02-08 13:40:01       38 阅读
  6. nginx限制网段访问

    2024-02-08 13:40:01       27 阅读
  7. NAND dummy read/write的原理和应用

    2024-02-08 13:40:01       33 阅读
  8. 数据结构_回文,相交题-2.4

    2024-02-08 13:40:01       36 阅读
  9. C++ 设计模式之单例模式

    2024-02-08 13:40:01       28 阅读
  10. 学习C语言的第4天

    2024-02-08 13:40:01       28 阅读
  11. B2071 余数相同问题(洛谷)

    2024-02-08 13:40:01       40 阅读