详解Spring Boot实战之Filter实现使用JWT进行接口认证

yizhihongxing

那我将为你详细讲解“详解Spring Boot实战之Filter实现使用JWT进行接口认证”的完整攻略。

1. 前言

在Web应用程序中,为了保障接口安全和数据的完整性,我们需要对访问接口的用户进行认证和授权。Spring Boot框架提供了多种认证和授权方式,其中,JWT是一种较为流行的认证方式。本文将通过Spring Boot实战教程来详细讲解如何使用Filter实现使用JWT进行接口认证。

2. JWT简介

JWT是Json Web Token的缩写,是一个轻量级的认证协议。它将用户身份信息以JSON格式保存在Token中,并使用密钥进行签名。在认证过程中,服务端只需对Token进行验证,从而达到用户认证和授权的目的。JWT的优点是不依赖Session,可以跨域传输。

JWT有3部分组成,分别是Header、Payload和Signature:

  • Header:Token的头部,包含算法和类型等信息;
  • Payload:Token的有效载荷,用于存储用户信息和其他用户相关的元数据;
  • Signature:尾部是用于验证Token是否被篡改的签名。

3. 实现步骤

3.1 引入相关依赖

在spring boot项目中,使用JWT需要引入json-web-token和jackson-databind两个依赖。在pom.xml文件中添加以下内容:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.7</version>
</dependency>

3.2 编写Token工具类

Token工具类用于生成和解析Token。在本例中,使用HS512算法和特定的密钥对Token进行签名,密钥采用硬编码方式存储。

import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;

@Component
public class JwtTokenUtils {

    // 过期时间30分钟
    private static final long EXPIRATION_TIME = 30 * 60 * 1000;

    // 密钥,硬编码,之后应该改为动态获取
    private static final String SECRET = "jwt_secret";

    /**
     * 生成Token
     * @param claims 载荷
     * @return Token
     */
    public static String generateToken(Map<String,Object> claims){
        Date now = new Date();
        Date expireDate = new Date(now.getTime() + EXPIRATION_TIME);
        JwtBuilder builder = Jwts.builder().setClaims(claims)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, SECRET);
        return builder.compact();
    }

    /**
     * 解析Token
     * @param token Token
     * @return 用户id
     */
    public static String getUserId(String token){
        try {
            Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
            return claims.getSubject();
        } catch (ExpiredJwtException e){
            throw new RuntimeException("登录已过期,请重新登录");
        } catch (UnsupportedJwtException e) {
            throw new RuntimeException("不支持该JWT类型");
        } catch (MalformedJwtException e) {
            throw new RuntimeException("无效的JWT token");
        } catch (SignatureException e) {
            throw new RuntimeException("无效的签名");
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("参数错误");
        }
    }
}

3.3 实现Filter

Filter是Servlet中的一种组件,它可以对请求和响应进行拦截和处理。在本例中,Filter的作用是对访问受保护接口的请求进行认证和授权。认证通过后,会将用户信息保存到Request对象中,方便后续操作使用。

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String path = request.getServletPath();
        if (!path.startsWith("/api/")) {
            chain.doFilter(request, response);
            return;
        }
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            try {
                token = token.substring(7);
                String userId = JwtTokenUtils.getUserId(token);
                Map<String, Object> user = getUserInfoFromDb(userId);
                if (user == null) {
                    response.setStatus(401);
                    return;
                } else {
                    request.setAttribute("user", user);
                    chain.doFilter(request, response);
                    return;
                }
            } catch (Exception e) {
                response.setStatus(401);
                return;
            }
        } else {
            response.setStatus(401);
            return;
        }
    }

    private Map<String, Object> getUserInfoFromDb(String userId){
        // TODO: 从数据库获取用户信息
        return null;
    }
}

3.4 注册Filter

使用Spring Boot,我们可以通过在配置类中添加Filter进行注册。在本例中,需要使用FilterRegistrationBean将Filter添加到过滤器链中。

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JwtConfig {

    @Bean
    public FilterRegistrationBean<JwtAuthenticationFilter> jwtAuthenticationFilter(){
        FilterRegistrationBean<JwtAuthenticationFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new JwtAuthenticationFilter());
        registrationBean.addUrlPatterns("/api/*");
        return registrationBean;
    }
}

4. 示例

为了方便演示,我们假设有一个用户注册和登陆接口,分别是:

POST /api/register
POST /api/login

其中,/api/login接口返回JWT Token。假设用户ID和用户名存储在用户信息表中,getUserInfoFromDb()方法从用户信息表中获取用户信息。

以下是注册和登录接口的示例代码。

4.1 注册接口

import org.springframework.web.bind.annotation.RequestBody;
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.UUID;

@RestController
public class RegisterController {

    @RequestMapping("/api/register")
    public Map<String,Object> register(@RequestBody Map<String,Object> params){
        String userId = UUID.randomUUID().toString();
        String username = (String) params.get("username");
        String password = (String) params.get("password");
        // TODO: 将用户信息存入数据库
        Map<String,Object> response = new HashMap<>();
        response.put("code", 200);
        response.put("msg", "注册成功");
        return response;
    }
}

4.2 登录接口

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;

@RestController
public class LoginController {

    @RequestMapping("/api/login")
    public Map<String,Object> login(@RequestBody Map<String,Object> params){
        String username = (String) params.get("username");
        String password = (String) params.get("password");
        // TODO: 验证用户名和密码,从数据库获取用户信息
        String userId = "fake_user_id";
        Map<String,Object> claims = new HashMap<>();
        claims.put("sub", userId);
        String token = JwtTokenUtils.generateToken(claims);
        Map<String,Object> response = new HashMap<>();
        response.put("code", 200);
        response.put("msg", "登录成功");
        response.put("token", "Bearer "+token);
        return response;
    }
}

以上示例中,我给出了简单的用户注册和登录逻辑,只是为了方便演示。实际使用过程中,需要根据实际情况进行相应的修改和完善。

5. 总结

本文通过一个实际的例子,讲解了如何使用Filter实现使用JWT进行接口认证。在实现过程中,我们使用了Java JWT和Spring Boot等技术,包括编写Token工具类、实现Filter以及注册Filter等操作。JWT的优点在于不依赖Session,可以跨域传输。在使用JWT时,我们需要注意密钥管理、过期时间设置等问题,保证Token的安全有效。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Spring Boot实战之Filter实现使用JWT进行接口认证 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • java实现Floyd算法

    Java实现Floyd算法 Floyd算法是解决图中最短路问题的一种经典算法,它可以求出图中任意两点之间的最短路径。下面我们将详细讲解如何使用Java实现Floyd算法。 算法思路 Floyd算法是一种动态规划算法,它通过逐步优化不同的路径来求取图中任意两点之间的最短路径。 我们可以用一个二维数组dis来存储图中任意两点之间的距离。具体地,dis[i][j]…

    Java 2023年5月18日
    00
  • SpringBoot Jpa企业开发示例详细讲解

    下面是针对“SpringBoot Jpa企业开发示例详细讲解”的完整攻略: 介绍 SpringBoot是当前非常流行的一款JavaWeb开发框架,而在企业中,数据库操作是非常常见的。基于这种需求,JPA是一种非常受欢迎的ORM(Object-Relational Mapping)框架,可以使开发者快速地进行数据库开发。在本篇攻略中,我们将介绍如何使用Spri…

    Java 2023年5月19日
    00
  • Java Apache Commons报错“PropertyVetoException”的原因与解决方法

    “PropertyVetoException”是Java的Apache Commons类库中的一个异常,通常由以下原因之一引起: 属性被否决:如果属性被否决,则可能会出现此异常。可能会尝试使用未定义的属性或尝试未正确配置属性。 以下是两个实例: 例1 如果属性被否决,则可以尝试使用正确的属性以解决此问题。例如,在Java中,可以使用以下代码: Bean be…

    Java 2023年5月5日
    00
  • MySQL示例讲解数据库约束以及表的设计

    “MySQL示例讲解数据库约束以及表的设计”是一篇比较综合性的文章,内容在开始之前应该分章节引出。以下是我根据自己的经验和理解对这个主题进行的完整攻略。 1. 关于数据库约束 “数据库约束”是指在创建数据库表时,针对表内字段相关的行为限制和处理措施。常见的数据库约束有NOT NULL约束、UNIQUE约束、PRIMARY KEY约束、FOREIGN KEY约…

    Java 2023年5月26日
    00
  • Spring security 自定义过滤器实现Json参数传递并兼容表单参数(实例代码)

    这里给出详细的“Spring security 自定义过滤器实现Json参数传递并兼容表单参数(实例代码)”攻略: 1. 概述 当我们用 Spring Security 来进行用户认证和授权时,为了保证安全性,一般使用 POST 请求提交表单参数,而不能使用 GET 请求进行参数传递。但是在某些情况下,我们需要通过 Json 参数来进行传递,此时就需要用到自…

    Java 2023年5月20日
    00
  • SpringBoot后端接口的实现(看这一篇就够了)

    “SpringBoot后端接口的实现(看这一篇就够了)”是一篇非常实用的文章,主要讲解了如何使用SpringBoot快速实现后端接口的开发。我将根据文章的内容为您提供一份完整攻略,帮助您理解和应用这篇文章。 1. 前置知识 在进行这个教程之前,您需要具备以下知识:- Java语言基础- SpringBoot框架基础- RESTful API的基本概念- Sp…

    Java 2023年5月15日
    00
  • Java C++ 题解leetcode857雇佣K名工人最低成本vector pair

    题目描述: 给定两个长度为N的整数数组,W数组表示每个工人的工资,Q数组表示每个工人完成工作的质量。现在要雇佣K名工人去完成一些工作,每个工人只能完成一项工作,工人完成一项工作的质量就是该工作质量的总和,而这些工作的总成本是所有工人的工资总和。求最小的总成本。 思路分析: 先将工资按比例排序,使用最小堆,维护当前最小的K个工资,同时记录下当前最小K个工资的序…

    Java 2023年5月20日
    00
  • Mybatis-Plus使用ID_WORKER生成主键id重复的解决方法

    下面为您提供详细的 “Mybatis-Plus使用ID_WORKER生成主键id重复的解决方法”攻略。 问题背景 Mybatis-Plus是一款高效便捷的持久层框架,它支持多种主键生成策略,包括UUID、雪花算法、自增、ID_WORKER等。其中,ID_WORKER是默认的主键生成策略,它通过Twitter的snowflake算法生成64位的唯一id,具有性…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部