Spring Boot 笔记 007 创建接口_登录

1.1 登录接口需求

Spring Boot 笔记 007 创建接口_登录_第1张图片

Spring Boot 笔记 007 创建接口_登录_第2张图片

1.2 JWT令牌

1.2.1 JWT原理

Spring Boot 笔记 007 创建接口_登录_第3张图片

1.2.2 引入JWT坐标

Spring Boot 笔记 007 创建接口_登录_第4张图片

1.2.3 单元测试

1.2.3.1 引入springboot单元测试坐标

Spring Boot 笔记 007 创建接口_登录_第5张图片

1.2.3.2 在单元测试文件夹中创建测试类

Spring Boot 笔记 007 创建接口_登录_第6张图片

1.2.3.3 运行测试类中的生成和解析方法

package com.geji;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.junit.jupiter.api.Test;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtTest {

    @Test
    public void testGen() {
        Map claims = new HashMap<>();
        claims.put("id", 1);
        claims.put("username", "张三");
        //生成jwt的代码
        String token = JWT.create()
                .withClaim("user", claims)//添加载荷
                .withExpiresAt(new Date(System.currentTimeMillis() + 1000*60))//添加过期时间
                .sign(Algorithm.HMAC256("geji"));//指定算法,配置秘钥

        System.out.println(token);

    }

    @Test
    public void testParse() {
        //定义字符串,模拟用户传递过来的token
        String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoxLCJ1c2VybmFtZSI6IuW8oOS4iSJ9LCJleHAiOjE3MDc4MTA0NTh9.Ir8IDQ673BoD86ubm8nMo_F91P-ytCd2_MaDzi5mONo";

        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("geji")).build();

        DecodedJWT decodedJWT = jwtVerifier.verify(token);//验证token,生成一个解析后的JWT对象
        Map claims = decodedJWT.getClaims();
        System.out.println(claims.get("user"));

        //如果篡改了头部和载荷部分的数据,那么验证失败
        //如果秘钥改了,验证失败
        //token过期
    }
}

1.2.4 在utils包中添加jwt工具类

Spring Boot 笔记 007 创建接口_登录_第7张图片

package com.geji.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

import java.util.Date;
import java.util.Map;

public class JwtUtil {

    private static final String KEY = "geji";
	
	//接收业务数据,生成token并返回
    public static String genToken(Map claims) {
        return JWT.create()
                .withClaim("claims", claims)
                .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 ))
                .sign(Algorithm.HMAC256(KEY));
    }

	//接收token,验证token,并返回业务数据
    public static Map parseToken(String token) {
        return JWT.require(Algorithm.HMAC256(KEY))
                .build()
                .verify(token)
                .getClaim("claims")
                .asMap();
    }

}

1.3 拦截器

1.3.1 编写拦截器

Spring Boot 笔记 007 创建接口_登录_第8张图片

package com.geji.interceptors;

import com.geji.pojo.Result;
import com.geji.utils.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Map;

@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //令牌验证
        String token = request.getHeader("Authorization");
        //验证token
        try{
            Map claims= JwtUtil.parseToken(token);

            return true;
        }catch (Exception e){
            response.setStatus(401);
            return false;
        }
    }


}

1.3.2 注册拦截器,登录和注册接口需要放行

Spring Boot 笔记 007 创建接口_登录_第9张图片

package com.geji.config;

import com.geji.interceptors.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 WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //登录接口和注册接口不拦截
        registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","/user/register");
    }
}

1.4 编写controller

1.4.1 编写login controller

Spring Boot 笔记 007 创建接口_登录_第10张图片

package com.geji.controller;

import com.geji.pojo.Result;
import com.geji.pojo.User;
import com.geji.service.UserService;
import com.geji.utils.JwtUtil;
import com.geji.utils.Md5Util;
import jakarta.validation.constraints.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/user")
@Validated
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public Result register(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {

        //查询用户
        User u = userService.findByUserName(username);
        if (u == null) {
            //没有占用
            //注册
            userService.register(username, password);
            return Result.success();
        } else {
            //占用
            return Result.error("用户名已被占用");
        }
    }

    @PostMapping("/login")
    public Result login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {
        //根据用户名查询用户
        User loginUser = userService.findByUserName(username);
        //判断该用户是否存在
        if (loginUser == null) {
            return Result.error("用户名错误");
        }

        //判断密码是否正确  loginUser对象中的password是密文
        if (Md5Util.getMD5String(password).equals(loginUser.getPassword())) {
            //登录成功
            Map claims = new HashMap<>();
            claims.put("id", loginUser.getId());
            claims.put("username", loginUser.getUsername());
            String token = JwtUtil.genToken(claims);
            //把token存储到redis中
//            ValueOperations operations = stringRedisTemplate.opsForValue();
//            operations.set(token,token,1, TimeUnit.HOURS);
            return Result.success(token);
        }
        return Result.error("密码错误");
    }
}

1.4.2 编写article list controller

Spring Boot 笔记 007 创建接口_登录_第11张图片

package com.geji.controller;

import com.geji.pojo.Result;
import com.geji.utils.JwtUtil;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@RequestMapping("/article")
public class ArticleController {
    @GetMapping("/list")
    public Result list(){
        return Result.success("所有文章数据...");

    }
}

1.5 测试

1.5.1 获取令牌

Spring Boot 笔记 007 创建接口_登录_第12张图片

1.5.2 带请求头

Spring Boot 笔记 007 创建接口_登录_第13张图片

1.4.3 不带请求头

Spring Boot 笔记 007 创建接口_登录_第14张图片

你可能感兴趣的:(Spring,Boot,spring,boot,笔记,java)