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

那我将为你详细讲解“详解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连接orcale数据库示例分享

    下面是详细的攻略。 Java连接Oracle数据库 准备工作 在开始之前,我们需要确保已经完成以下准备工作: 安装Oracle数据库:在官网中下载并安装Oracle数据库,安装完成后配置好环境变量。 下载Oracle JDBC驱动:在官网中下载对应版本的JDBC驱动,将其复制到Java项目中。 示例1:使用JDBC API进行数据库操作 以下是连接Oracl…

    Java 2023年6月1日
    00
  • 详解Java中的延时队列 DelayQueue

    详解Java中的延时队列 DelayQueue 概述 DelayQueue是Java中的一个实现了Delayed的队列,它按照剩余时间从少到多的顺序对元素进行排序,每个元素都有一个过期时间,只有过期的元素才能被取出。 延时队列的实现 延时队列的实现需要实现Delayed接口,并重写getDelay()方法和compareTo()方法。 public inte…

    Java 2023年5月26日
    00
  • Java实现简单登陆界面

    想要实现Java实现简单登录界面,需要遵循以下步骤: 步骤一:创建Java项目 在IDE中,创建一个Java项目(比如使用Eclipse),并选择创建一个Java程序。该程序将成为登录界面的入口。 步骤二:设计登录界面 使用Swing或JavaFX等Java GUI库,设计登录界面的界面元素。例如,需要一个文本框来输入用户名,一个密码框来输入密码,还需要一个…

    Java 2023年5月18日
    00
  • MyBatis-Plus简介和快速入门教程

    MyBatis-Plus简介和快速入门教程 简介 MyBatis-Plus是基于MyBatis的增强工具,提供了常用的增删改查、分页、乐观锁、逻辑删除等功能,简化了开发人员的工作,提高了开发效率。同时 MyBatis-Plus 也支持 Lambda 表达式查询、自动代码生成等高级功能。 MyBatis-Plus 的主要特点如下: 支持自动生成代码; 内置通用…

    Java 2023年5月20日
    00
  • Spring注解驱动之ApplicationListener异步处理事件说明

    在Spring应用程序中,我们可以使用ApplicationListener接口来处理应用程序事件。在本文中,我们将详细介绍如何使用ApplicationListener异步处理事件,并提供两个示例说明。 1. ApplicationListener接口 ApplicationListener接口是Spring框架中的一个接口,用于处理应用程序事件。当应用程…

    Java 2023年5月18日
    00
  • 一篇文章带你入门java集合

    一篇文章带你入门Java集合 Java集合是Java编程中常用的数据结构,包含了List、Set、Map等常用的集合类型。本文将从以下几个方面介绍Java集合: Java集合的类型和概念 Java集合的基础用法 Java集合的注意事项 1. Java集合的类型和概念 集合类型 Java集合主要有以下三种类型: List(列表):有序,可以重复,例如Array…

    Java 2023年5月26日
    00
  • SpringBoot教程_创建第一个SpringBoot项目

    以下是创建第一个SpringBoot项目的完整攻略,包含两条示例: 一、前置条件 在开始创建SpringBoot项目之前,请确认你已经完成以下步骤: 安装好Java开发环境。建议使用JDK8及以上版本。 安装好Maven构建工具。 二、创建SpringBoot项目 1. 使用Spring Initializr创建项目 首先,我们使用Spring Initia…

    Java 2023年5月15日
    00
  • Java中统计字符个数以及反序非相同字符的方法详解

    Java中统计字符个数的方法详解 在Java中可以使用几种方法来统计字符串中字符的个数,下面介绍一些常用的方法。 1.使用for循环 可以使用for循环遍历字符串,逐个判断字符是否相同或满足某些条件,从而统计字符个数。 示例代码: public int countChar(String str, char c) { int count = 0; for (i…

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