iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >SpringBoot结合JWT实现用户登录、注册、鉴权
  • 949
分享到

SpringBoot结合JWT实现用户登录、注册、鉴权

SpringBootJWT登录注册鉴权 2023-05-19 20:05:56 949人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录一、用户注册与登录二、用户鉴权用户登录、注册及鉴权是我们基本所有系统必备的,也是很核心重要的一块,这一块的安全性等都比较重要,实现的方案其实也有几种,从以前的cookie+ses

用户登录、注册及鉴权是我们基本所有系统必备的,也是很核心重要的一块,这一块的安全性等都比较重要,实现的方案其实也有几种,从以前的cookie+session的方案,到现在常用的Jwt的方案,这篇文章就讲讲目前在公司中最常用的jwt方案如何实现。

一、用户注册与登录

完成用户注册与登录有个核心点就是密码的加密与验证,我们目前比较常用的方案是密码+盐再采用MD5加密的方案,

盐的方式一般可以在application.yml里面写死,但安全性相对较差,还有就是通过UUID生成存到数据库里,这里我们采用第二种安全性更高的方式。

sql如下:

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `passWord` varchar(255) NOT NULL,
  `salt` varchar(255) NOT NULL,
  `admin` int(1) DEFAULT '0',
  `age` int(3) NOT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `deleted` int(1) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

对应的User实体类

domian.entity.User:

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@TableName("user")
public class User {
    @TableId
    private Long id;
    private String username;
    private String password;
    private String salt;
    private Boolean admin;
    private Integer age;
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    private Integer deleted;
}

这里我们使用了Mybatis Plus的逻辑删除及自动填充功能,不太清楚的可以看看我的文章SpringBoot 整合 Mybatis Plus 实现基本CRUD功能

接收用户注册信息的DTO

domain.dto.reGIStryUserDto:

import com.fasterxml.jackson.annotation.JSONIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.UUID;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class registryUserDto {
    private String username;
    private String password;
    @jsonIgnore
    private String salt = UUID.randomUUID().toString().replaceAll("-", "");
    private Boolean admin;
    private Integer age;
}

@JsonIgnore为忽略前端的传值,这里使用我们UUID生成的值。

用户登录的DTO

domain.dto.LoginUserDto:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginUserDto {
    private String username;
    private String password;
}

用户注册与登录的controller:

controller.UserController:

import com.jk.domain.dto.registryUserDto;
import com.jk.domain.dto.LoginUserDto;
import com.jk.service.UserService;
import com.jk.domain.vo.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.WEB.bind.annotation.*;
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @PostMapping("/registry")
    public ResponseResult registryUser(@RequestBody registryUserDto registryUserDto) {
        return userService.registryUser(registryUserDto);
    }
    @PostMapping("/login")
    public ResponseResult login(@RequestBody LoginUserDto loginUserDto) {
        return userService.login(loginUserDto);
    }
}

用户注册与登录的service:

service.UserService:

import com.jk.domain.dto.registryUserDto;
import com.jk.domain.dto.LoginUserDto;
import com.jk.domain.vo.ResponseResult;
public interface UserService {
    ResponseResult registryUser(registryUserDto registryUserDto);
    ResponseResult login(LoginUserDto loginUserDto);
}

用户注册与登录的service实现类:

service.impl.UserServiceImpl:

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jk.domain.dto.registryUserDto;
import com.jk.domain.dto.LoginUserDto;
import com.jk.domain.entity.User;
import com.jk.enums.AppHttpCodeEnum;
import com.jk.mapper.UserMapper;
import com.jk.service.UserService;
import com.jk.domain.vo.ResponseResult;
import com.jk.utils.BeanCopyUtils;
import com.jk.utils.JwtUtils;
import com.jk.utils.RedisCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import java.util.concurrent.TimeUnit;
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisCache redisCache;
    @Override
    public ResponseResult registryUser(registryUserDto registryUserDto) {
        String password = registryUserDto.getPassword();
        String salt = registryUserDto.getSalt();
        String md5Password = DigestUtils.md5DigestAsHex((password + salt).getBytes());
        registryUserDto.setPassword(md5Password);
        User user = BeanCopyUtils.copyBean(registryUserDto, User.class);
        userMapper.insert(user);
        return ResponseResult.okResult();
    }
    @Override
    public ResponseResult login(LoginUserDto loginUserDto) {
        String username = loginUserDto.getUsername();
        String password = loginUserDto.getPassword();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        User user = userMapper.selectOne(queryWrapper);
        String md5Password = DigestUtils.md5DigestAsHex((password + user.getSalt()).getBytes());
        if (!md5Password.equals(user.getPassword())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_ERROR);
        }
        String token = JwtUtils.createToken(user.getId());
        redisCache.setCacheObject("TOKEN_" + token, JSON.toJSONString(user), 1, TimeUnit.DAYS);
        return ResponseResult.okResult(token);
    }
}

用户注册时,我们把密码+salt进行MD5加密,然后入库,用户登录时,根据username查出用户,再把用户传入的密码+salt进行MD5加密数据库查出的用户进行密码比较判断是否验证通过。这里还有使用到一个JWT工具,验证通过后使用JWT工具类生成token和用户信息存到redis里面,这里需要引入下fastjson来对用户信息字符串化存,然后返回前端token

具体JWT使用如下:

  • 首先引入fastjsonjwt的依赖包
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>2.0.26</version>
</dependency>
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>
  • JWT工具类的封装

utils.JwtUtils:

import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlGorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtils {
    private static final String jwtToken = "1234567890p[]l;'";
    public static String createToken(Long userId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        JwtBuilder jwtBuilder = Jwts.builder()
                // 设置有效载荷
                .setClaims(claims)
                // 设置签发时间
                .setIssuedAt(new Date())
                // 设置过期时间
                .setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 60 * 1000))
                // 采用HS256方式签名,key就是用来签名的秘钥
                .signWith(SignatureAlgorithm.HS256, jwtToken);
        String token = jwtBuilder.compact();
        return token;
    }
    public static Map<String, Object> checkToken(String token) {
        try {
            Jwt parse = Jwts.parser().setSigningKey(jwtToken).parse(token);
            return (Map<String, Object>) parse.getBody();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

到此我们已经完成了用户的注册和登录功能。但还有一个问题就是用户鉴权,我们在调用其他接口时如何判断用户是否已登录。

二、用户鉴权

用户鉴权我们需要用到ThreadLocal来存储用户信息,我们首先创建这个工具类

utils.UserThreadLocal:

import com.jk.domain.entity.User;
public class UserThreadLocal {
    private UserThreadLocal() {
    }
    private static final ThreadLocal<User> LOCAL = new ThreadLocal<>();
    public static void put(User user) {
        LOCAL.set(user);
    }
    public static User get() {
        return LOCAL.get();
    }
    public static void remove() {
        LOCAL.remove();
    }
}

还需要在service中实现验证token的逻辑

service.UserService:

User checkToken(String token);

service.impl.UserServiceImpl:

@Override
public User checkToken(String token) {
    if (StringUtils.isEmpty(token)) {
        return null;
    }
    Map<String, Object> map = JwtUtils.checkToken(token);
    if (map == null) {
        return null;
    }
    String userJson =  redisCache.getCacheObject("TOKEN_" + token);
    if (StringUtils.isEmpty(userJson)) {
        return null;
    }
    User user = JSON.parseObject(userJson, User.class);
    return user;
}

使用拦截器实现token验证

handler.interceptor.LoginInterceptor:

import com.jk.domain.entity.User;
import com.jk.enums.AppHttpCodeEnum;
import com.jk.exception.SystemException;
import com.jk.service.UserService;
import com.jk.utils.UserThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.httpservletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private UserService userService;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        String token = request.getHeader("token");
        log.info("===============request start===============");
        log.info("request uri:{}", request.getRequestURI());
        log.info("request method:{}", request.getMethod());
        log.info("token:{}", token);
        log.info("===============request end===============");
        if (StringUtils.isEmpty(token)) {
            throw new SystemException(AppHttpCodeEnum.NEED_LOGIN);
        }
        User user = userService.checkToken(token);
        if (user == null) {
            throw new SystemException(AppHttpCodeEnum.NEED_LOGIN);
        }
        UserThreadLocal.put(user);
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserThreadLocal.remove();
    }
}

配置WebmvcConfigurer使用登录拦截器

import com.jk.handler.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
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 WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/web/**")
                .addPathPatterns("/admin/**");
    }
}

会对/web/admin的所有接口做登录验证,这个大家根据自己项目需求调整。

到此这篇关于SpringBoot结合JWT实现用户登录、注册、鉴权的文章就介绍到这了,更多相关SpringBoot JWT用户登录、注册、鉴权内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: SpringBoot结合JWT实现用户登录、注册、鉴权

本文链接: https://www.lsjlt.com/news/213695.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SpringBoot结合JWT实现用户登录、注册、鉴权
    目录一、用户注册与登录二、用户鉴权用户登录、注册及鉴权是我们基本所有系统必备的,也是很核心重要的一块,这一块的安全性等都比较重要,实现的方案其实也有几种,从以前的cookie+ses...
    99+
    2023-05-19
    SpringBoot JWT 登录 注册 鉴权
  • SpringBoot结合JWT登录权限控制的实现
    目录一、准备LoginUser(存放登录用户信息) 和JwtUser二、准备JwtTokenUtils三、准备JWTAuthenticationFilter (验证登录)、JWTAu...
    99+
    2022-11-13
  • springsecurity结合jwt实现用户重复登录处理
    目录背景方案思路图核心代码背景 近日,客户针对我司系统做一些列漏洞扫描,最后总结通用漏洞有如下: 用户重复登录接口未授权接口越权访问 针对以上漏洞,分三篇文章分别记录解决方案,供后续...
    99+
    2022-11-13
  • SpringBoot+JWT实现注册、登录、状态续签流程分析
    目录一、实现流程1.注册2.登录3.登录保持【状态续签】二、实现方法1.引入依赖2.application配置文件3.mysql建表4.Bean三、测试1.注册2.登录3.状态续签【...
    99+
    2022-11-13
  • Python实现用户登录注册
    简单的Python代码:用户登录注册 利用业余时间,写了一个用户进行登录注册的代码,非常简单。主要实现的功能是: 1、可以进行用户登录,在用户进行登录之前,对用户名进行检查,查看是否...
    99+
    2022-11-13
  • QT实现用户登录注册
    本文实例为大家分享了QT实现用户登录注册的具体代码,供大家参考,具体内容如下 #include "widget.h" #include "ui_widget.h" //窗口设置 #...
    99+
    2022-11-13
  • Python实现用户注册登录程序
    本文实例为大家分享了Python实现用户注册登录程序的具体代码,供大家参考,具体内容如下 要求: 1.支持多个用户登录(把已有的用户名和密码存放在一个文件中,锁定的用户名存放在另一个...
    99+
    2022-11-13
  • QT如何实现用户登录注册
    本篇内容主要讲解“QT如何实现用户登录注册”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“QT如何实现用户登录注册”吧!具体代码如下#include "widget.h&quo...
    99+
    2023-07-02
  • QT实现用户登录注册功能
    本文实例为大家分享了QT实现用户登录注册的具体代码,供大家参考,具体内容如下 1、login.h #ifndef LOGIN_H #define LOGIN_H #include ...
    99+
    2022-11-13
  • JavaWeb实现用户登录与注册功能
    本文实例为大家分享了JavaWeb实现用户登录与注册的具体代码,供大家参考,具体内容如下 所用知识 客户端:HTML CSS JS (JQuery) 服务器:JAVA基础 ...
    99+
    2022-11-12
  • Java-web实现用户登录、注册功能
    源码在资源里 目录 环境搭建数据库 用户登录需求分析代码实现编写UserMapper类编写User类编写loginServlet类编写login.html编写login.css ...
    99+
    2023-10-10
    java 前端 servlet
  • Node.js+Express+MySql实现用户登录注册功能
    本文实例为大家分享了Node.js实现用户登录注册的具体代码,供大家参考,具体内容如下 IDE:WebStorm 工程目录: 数据库表 Login.js: var express=r...
    99+
    2022-06-04
    用户登录 功能 js
  • node.js+jQuery实现用户登录注册AJAX交互
    最近实现了Node.js当作后台,jQuery写前台AJAX代码的,实现用户登录和注册的功能,刷新了前后端交互的三观。特记录一下。 1.login.ejs实现form框架 <form >...
    99+
    2022-06-04
    用户登录 js node
  • JS+PHP如何实现用户注册及登录
    小编给大家分享一下JS+PHP如何实现用户注册及登录,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!<!DOCTYPE ht...
    99+
    2022-10-19
  • php 怎么实现用户注册登录界面
    本教程操作环境:Windows7系统、PHP8.1版、Dell G3电脑。php 怎么实现用户注册登录界面?PHP登录与注册页面简单实现(包含数据库验证)(包含数据库)log.php(登录主界面)由于是简单的页面,登录页面只做了数据库验证,...
    99+
    2022-11-19
    php
  • QT如何实现用户登录注册功能
    这篇文章主要介绍“QT如何实现用户登录注册功能”,在日常操作中,相信很多人在QT如何实现用户登录注册功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”QT如何实现用户登录注册功能”的疑惑有所帮助!接下来,请跟...
    99+
    2023-07-02
  • php如何实现用户注册登录界面
    今天小编给大家分享一下php如何实现用户注册登录界面的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。php实现用户注册登录界面...
    99+
    2023-07-04
  • JavaWeb实战之用Servlet+JDBC实现用户登录与注册
    目录一、前言二、准备工作三、编写web层一、前言 使用到的技术栈: (1)JDBC (2)Servlet (3)MySQL 二、准备工作 (1)书城用户数据库与表创建 (2)编写用户...
    99+
    2022-11-12
  • node.js+jQuery如何实现用户登录注册AJAX交互
    这篇文章给大家分享的是有关node.js+jQuery如何实现用户登录注册AJAX交互的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1.login.ejs实现form框架&nbs...
    99+
    2022-10-19
  • Node.js+Express+MySql如何实现用户登录注册功能
    这篇文章主要介绍了Node.js+Express+MySql如何实现用户登录注册功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。具体内容如...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作