Springboot | 零基础快速搭建JWT简单登录案例(一)

目录

依赖

Yaml配置

数据库设计

实体类

Dao(Mapper)层

服务层

服务接口  UserService

实现服务接口  UserServiceImpl

控制器层

应用类(JWT)

启动类


依赖

        <!-- JWT -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>

        <!-- mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.7</version>
        </dependency>

        <!-- JDBC -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

Yaml配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/这里是数据库名?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
    username: 你的数据库账号
    password: 你的数据库密码

mybatis-plus:
  configuration:
    #这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    call-setters-on-nulls: true

数据库设计

实体类

package com.takem.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;


@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@TableName("users") //数据库表
public class Users {
    @TableField(value = "user_pid") //字段名
    private Integer userPid;

    @TableField(value = "user_name")
    private String userName;

    @TableField(value = "user_password")
    private String userPassword;

    @TableField(value = "user_role")
    private String userRole;

    @TableField(value = "user_register_time")
    private String userRegisterTime;

}

Dao(Mapper)层

package com.takem.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.takem.entity.Users;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UsersMapper extends BaseMapper<Users> {

}

服务层

服务接口  UserService

package com.takem.service;

import com.takem.entity.Users;

import java.util.List;

public interface UserService {

    // 查询单个用户与账号密码
    Integer SelectOneUser(String userName,String userPassword);

}

实现服务接口  UserServiceImpl

package com.takem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.takem.entity.Users;
import com.takem.mapper.UsersMapper;
import com.takem.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl  implements UserService{

    private final UsersMapper userMapper;

    @Autowired
    public UserServiceImpl(UsersMapper usersMapper) {
        this.userMapper = usersMapper;
    }


    // 查询 用户账号密码 并返回id
    @Override
    public Integer SelectOneUser(String userName,String userPassword) {
        QueryWrapper<Users> queryWrapper  = new QueryWrapper<>();
        try {
            queryWrapper.eq("user_name",userName).eq("user_password",userPassword);
            return userMapper.selectOne(queryWrapper).getUserPid();
        }catch (Exception e){
            return 0;
        }
    }
}

控制器层

package com.takem.controller;


import com.auth0.jwt.interfaces.DecodedJWT;
import com.takem.service.impl.UserServiceImpl;
import com.takem.util.JwtTokenUtil;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
@AllArgsConstructor
public class AuthController {
    private JwtTokenUtil jwtTokenUtil;

    private UserServiceImpl userService;


    // 登录系统-获取token-并嵌入cookie中
    @GetMapping("login")
    public String webLogin(String username, String password, HttpServletRequest request, HttpServletResponse response){
        // 先去查询数据库中是否存在该用户
        Integer userId = userService.SelectOneUser(username, password);
        if (userId > 0) {
            // 登录成功后需要去获取token 同时嵌入再网站内的cookie中
            String token = jwtTokenUtil.generateToken(userId,username);

            // 将token放入请求头中
            Cookie cookie = new Cookie("token", token);
            cookie.setPath("/");
            cookie.setHttpOnly(true);
            cookie.setMaxAge(36000); // cookie有效时间
            cookie.setSecure(true);

            response.addCookie(cookie);

            return "登录成功!\n"+token;
        }else {
            return "账号或密码错误!";
        }
    }


    // 访问首页
    @GetMapping("index")
    public String onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response){
        // 从cookie中获取token值
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("token".equals(cookie.getName())) {
                    String userToken = cookie.getValue();
                    if (jwtTokenUtil.validateToken(userToken)) {
                        return "登录成功!xxx";
                    }else {
                        return "账号或密码错误!";
                    }
                }
            }
        }
        return "cookie中找不到token";
    }
}

应用类(JWT)

package com.takem.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.stereotype.Component;

import java.util.Calendar;


@Component
public class JwtTokenUtil {
    private static final String TOKENKEY = "chenchen"; // 随机盐
    private static final long EXPIRATION = 86400000; // token有效时间(毫秒)

    //生成Token
    public String generateToken(Integer userId , String userName) {

        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND, (int)EXPIRATION);

        String token = JWT.create()//生成令牌
                .withClaim("userId", userId)//payload
                .withClaim("username", userName)//设置自定义用户名
                .withExpiresAt(instance.getTime())//设置令牌的有效时间
                .sign(Algorithm.HMAC256(TOKENKEY))//设置签名 保密 复杂
                ;
        System.out.println(token);//输出令牌
        return token;
    }


    // 验证token
    public Boolean validateToken(String token) {
        if (token == null || token.isEmpty()) {
            System.out.println("Token is null or empty");
            return false;
        }
        try {
             // 检查token是否包含两个点号,这是JWT标准格式的一部分
            if (token.split("\\.").length != 3) {
                System.out.println("Invalid token format");
                return false;
            }
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(TOKENKEY)).build();
            try {
                DecodedJWT decodedJWT = jwtVerifier.verify(token);
                System.out.println("用户Id:" + decodedJWT.getClaim("userId").asInt());
                System.out.println("用户名:" + decodedJWT.getClaim("username").asString());
                System.out.println("过期时间:" + decodedJWT.getExpiresAt());
                return true;
            }catch (Exception e){
                if (e instanceof TokenExpiredException) {
                    System.out.println("Token已过期");
                } else if (e instanceof SignatureVerificationException) {
                    System.out.println("签名验证失败");
                } else if (e instanceof JWTVerificationException) {
                    System.out.println("JWT验证失败: " + e.getMessage());
                } else {
                    System.out.print("未知错误: ");
                    e.printStackTrace();
                }
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }
}

启动类

package com.takem;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.takem.mapper")
public class TakeMApplication {

    public static void main(String[] args) {
        SpringApplication.run(TakeMApplication.class, args);
    }

}

(到底啦,更多案例可关注 公棕号 : wmcode )

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-13 04:10:02       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-13 04:10:02       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-13 04:10:02       57 阅读
  4. Python语言-面向对象

    2024-07-13 04:10:02       68 阅读

热门阅读

  1. C++中struct与class区别,C与C++中struct区别

    2024-07-13 04:10:02       31 阅读
  2. HTTPS和HTTP有哪些区别

    2024-07-13 04:10:02       20 阅读
  3. Qt开发 | Qt创建线程 | Qt并发-QtConcurrent

    2024-07-13 04:10:02       15 阅读
  4. UI图标库推荐网站

    2024-07-13 04:10:02       20 阅读
  5. 从零开始学习cartographer源码之01.gflags与glog

    2024-07-13 04:10:02       15 阅读
  6. [NeetCode 150] Valid Sudoku

    2024-07-13 04:10:02       20 阅读