当前位置: 代码网 > it编程>编程语言>Java > 在Spring Security中集成JWT实现无状态认证

在Spring Security中集成JWT实现无状态认证

2026年08月05日 Java 我要评论
1. spring security 集成 jwt 概述json web token(jwt)是一种用于在网络应用间安全传递信息的开放标准(rfc 7519)。spring security 集成 j

1. spring security 集成 jwt 概述

json web token(jwt)是一种用于在网络应用间安全传递信息的开放标准(rfc 7519)。spring security 集成 jwt 可以实现无状态的身份验证和授权机制,在电商系统中常用于用户登录认证和权限管理。

2. 搭建 jwt 认证工程

2.1 依赖添加

pom.xml 中添加 spring security、spring boot web、jjwt 等必要依赖。

<dependencies>
    <!-- spring boot web -->
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-web</artifactid>
    </dependency>
    <!-- spring security -->
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-security</artifactid>
    </dependency>
    <!-- jjwt -->
    <dependency>
        <groupid>io.jsonwebtoken</groupid>
        <artifactid>jjwt</artifactid>
        <version>0.9.1</version>
    </dependency>
    <!-- redis -->
    <dependency>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-data-redis</artifactid>
    </dependency>
</dependencies>

2.2 配置 spring security

创建 spring security 配置类,配置认证和授权规则。

import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.security.config.annotation.web.builders.httpsecurity;
import org.springframework.security.config.annotation.web.configuration.enablewebsecurity;
import org.springframework.security.config.annotation.web.configuration.websecurityconfigureradapter;
import org.springframework.security.config.http.sessioncreationpolicy;
import org.springframework.security.web.authentication.usernamepasswordauthenticationfilter;

@configuration
@enablewebsecurity
public class securityconfig extends websecurityconfigureradapter {

    private final jwtauthenticationfilter jwtauthenticationfilter;

    public securityconfig(jwtauthenticationfilter jwtauthenticationfilter) {
        this.jwtauthenticationfilter = jwtauthenticationfilter;
    }

    @override
    protected void configure(httpsecurity http) throws exception {
        http
           .csrf().disable()
           .sessionmanagement().sessioncreationpolicy(sessioncreationpolicy.stateless)
           .and()
           .authorizerequests()
               .antmatchers("/api/auth/login").permitall()
               .anyrequest().authenticated()
               .and()
           .addfilterbefore(jwtauthenticationfilter, usernamepasswordauthenticationfilter.class);
    }
}

3. 使用 jwt 认证

3.1 生成 jwt

创建 jwt 工具类,用于生成和解析 jwt。

import io.jsonwebtoken.claims;
import io.jsonwebtoken.jwts;
import io.jsonwebtoken.signaturealgorithm;
import org.springframework.beans.factory.annotation.value;
import org.springframework.stereotype.component;

import java.util.date;

@component
public class jwtutils {

    @value("${jwt.secret}")
    private string secret;

    @value("${jwt.expirationms}")
    private int expirationms;

    public string generatejwttoken(string username) {
        return jwts.builder()
               .setsubject(username)
               .setissuedat(new date())
               .setexpiration(new date((new date()).gettime() + expirationms))
               .signwith(signaturealgorithm.hs512, secret)
               .compact();
    }

    public string getusernamefromjwttoken(string token) {
        return jwts.parser().setsigningkey(secret).parseclaimsjws(token).getbody().getsubject();
    }

    public boolean validatejwttoken(string authtoken) {
        try {
            jwts.parser().setsigningkey(secret).parseclaimsjws(authtoken);
            return true;
        } catch (exception e) {
            return false;
        }
    }
}

3.2 认证过滤器

创建 jwt 认证过滤器,用于拦截请求并验证 jwt。

import io.jsonwebtoken.expiredjwtexception;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.security.authentication.usernamepasswordauthenticationtoken;
import org.springframework.security.core.context.securitycontextholder;
import org.springframework.security.core.userdetails.userdetails;
import org.springframework.security.core.userdetails.userdetailsservice;
import org.springframework.security.web.authentication.webauthenticationdetailssource;
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;

@component
public class jwtauthenticationfilter extends onceperrequestfilter {

    @autowired
    private jwtutils jwtutils;

    @autowired
    private userdetailsservice userdetailsservice;

    @override
    protected void dofilterinternal(httpservletrequest request, httpservletresponse response, filterchain filterchain)
            throws servletexception, ioexception {
        try {
            string jwt = parsejwt(request);
            if (jwt != null && jwtutils.validatejwttoken(jwt)) {
                string username = jwtutils.getusernamefromjwttoken(jwt);

                userdetails userdetails = userdetailsservice.loaduserbyusername(username);
                usernamepasswordauthenticationtoken authentication = new usernamepasswordauthenticationtoken(
                        userdetails, null, userdetails.getauthorities());
                authentication.setdetails(new webauthenticationdetailssource().builddetails(request));

                securitycontextholder.getcontext().setauthentication(authentication);
            }
        } catch (expiredjwtexception e) {
            // 处理 jwt 过期异常
        }

        filterchain.dofilter(request, response);
    }

    private string parsejwt(httpservletrequest request) {
        string headerauth = request.getheader("authorization");

        if (headerauth != null && headerauth.startswith("bearer ")) {
            return headerauth.substring(7);
        }

        return null;
    }
}

4. 使用 redis 解决退出时 jwt 不能过期问题

4.1 redis 配置和启动

application.properties 中配置 redis 连接信息。

spring.redis.host=localhost
spring.redis.port=6379

确保 redis 服务已启动,可以使用 docker 快速启动 redis 容器。

docker run -p 6379:6379 redis

4.2 将 jwt 放到 redis 中

创建 redis 工具类,用于操作 redis 存储 jwt。

import org.springframework.beans.factory.annotation.autowired;
import org.springframework.data.redis.core.redistemplate;
import org.springframework.stereotype.component;

import java.util.concurrent.timeunit;

@component
public class redisutils {

    @autowired
    private redistemplate<string, string> redistemplate;

    public void set(string key, string value, long timeout, timeunit unit) {
        redistemplate.opsforvalue().set(key, value, timeout, unit);
    }

    public boolean haskey(string key) {
        return redistemplate.haskey(key);
    }

    public void delete(string key) {
        redistemplate.delete(key);
    }
}

4.3 解决退出问题

在用户退出时,将 jwt 存入 redis 黑名单,后续验证时检查 jwt 是否在黑名单中。

import org.springframework.beans.factory.annotation.autowired;
import org.springframework.web.bind.annotation.postmapping;
import org.springframework.web.bind.annotation.requestheader;
import org.springframework.web.bind.annotation.restcontroller;

import java.util.concurrent.timeunit;

@restcontroller
public class authcontroller {

    @autowired
    private jwtutils jwtutils;

    @autowired
    private redisutils redisutils;

    @postmapping("/api/auth/logout")
    public string logout(@requestheader("authorization") string authorizationheader) {
        string jwt = authorizationheader.substring(7);
        long expiration = jwtutils.getexpirationdatefromjwttoken(jwt).gettime() - system.currenttimemillis();
        redisutils.set(jwt, "blacklisted", expiration, timeunit.milliseconds);
        return "logged out successfully";
    }
}

5. 示例总结

  • 工程搭建:添加必要依赖,配置 spring security 实现基本的认证和授权规则。
  • jwt 认证:使用 jjwt 库生成和解析 jwt,创建认证过滤器拦截请求并验证 jwt。
  • redis 集成:配置 redis 连接信息,使用 redis 存储 jwt 黑名单,解决 jwt 退出不能过期的问题。

以上就是在spring security中集成jwt实现无状态认证的详细内容,更多关于spring security集成jwt无状态认证的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com