当前位置: 代码网 > it编程>编程语言>Java > Spring Boot集成JWT实现无状态认证与授权方式

Spring Boot集成JWT实现无状态认证与授权方式

2025年11月18日 Java 我要评论
在spring boot中集成jwt(json web token)是一种常见的身份验证和授权方式。jwt是一种无状态的、基于令牌的认证机制,可以用于保护api接口的安全性。1. 添加依赖首先,在po

在spring boot中集成jwt(json web token)是一种常见的身份验证和授权方式。jwt是一种无状态的、基于令牌的认证机制,可以用于保护api接口的安全性。

1. 添加依赖

首先,在pom.xml文件中添加jwt相关的依赖。通常使用java-jwt库或jjwt库。这里以jjwt为例:

<dependency>
    <groupid>io.jsonwebtoken</groupid>
    <artifactid>jjwt</artifactid>
    <version>0.9.1</version>
</dependency>

如果使用spring security,还需要添加spring security的依赖:

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-security</artifactid>
</dependency>

2. 配置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;
import java.util.hashmap;
import java.util.map;
import java.util.function.function;
@component
public class jwtutil {
    @value("${jwt.secret}")
    private string secret;
    public string extractusername(string token) {
        return extractclaim(token, claims::getsubject);
    }
    public date extractexpiration(string token) {
        return extractclaim(token, claims::getexpiration);
    }
    public <t> t extractclaim(string token, function<claims, t> claimsresolver) {
        final claims claims = extractallclaims(token);
        return claimsresolver.apply(claims);
    }
    private claims extractallclaims(string token) {
        return jwts.parser().setsigningkey(secret).parseclaimsjws(token).getbody();
    }
    private boolean istokenexpired(string token) {
        return extractexpiration(token).before(new date());
    }
    public string generatetoken(string username) {
        map<string, object> claims = new hashmap<>();
        return createtoken(claims, username);
    }
    private string createtoken(map<string, object> claims, string subject) {
        return jwts.builder()
                .setclaims(claims)
                .setsubject(subject)
                .setissuedat(new date(system.currenttimemillis()))
                .setexpiration(new date(system.currenttimemillis() + 1000 * 60 * 60 * 10)) // 10小时
                .signwith(signaturealgorithm.hs256, secret)
                .compact();
    }
    public boolean validatetoken(string token, string username) {
        final string extractedusername = extractusername(token);
        return (extractedusername.equals(username) && !istokenexpired(token));
    }
}

3. 配置spring security

创建一个securityconfig类来配置spring security,使其支持jwt认证。

import org.springframework.beans.factory.annotation.autowired;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.security.authentication.authenticationmanager;
import org.springframework.security.config.annotation.authentication.builders.authenticationmanagerbuilder;
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.core.userdetails.userdetailsservice;
import org.springframework.security.crypto.bcrypt.bcryptpasswordencoder;
import org.springframework.security.crypto.password.passwordencoder;
@configuration
@enablewebsecurity
public class securityconfig extends websecurityconfigureradapter {
    @autowired
    private jwtrequestfilter jwtrequestfilter;
    @autowired
    private userdetailsservice userdetailsservice;
    @override
    protected void configure(authenticationmanagerbuilder auth) throws exception {
        auth.userdetailsservice(userdetailsservice).passwordencoder(passwordencoder());
    }
    @override
    protected void configure(httpsecurity http) throws exception {
        http
                .csrf().disable()
                .authorizerequests()
                .antmatchers("/authenticate").permitall()
                .anyrequest().authenticated()
                .and()
                .sessionmanagement().sessioncreationpolicy(sessioncreationpolicy.stateless);
       .add httpfilterbefore(jwtrequestfilter, usernamepasswordauthenticationfilter.class);
    }
    @override
    @bean
    public authenticationmanager authenticationmanagerbean() throws exception {
        return super.authenticationmanagerbean();
    }
    @bean
    public passwordencoder passwordencoder() {
        return new bcryptpasswordencoder();
    }
}

4. 创建jwt请求过滤器

创建一个jwtrequestfilter类,用于在每个请求中解析jwt,并将其设置到spring security上下文中。

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.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 jwtrequestfilter extends onceperrequestfilter {
    @autowired
    private jwtutil jwtutil;
    @autowired
    private userdetailsservice userdetailsservice;
    @override
    protected void dofilterinternal(httpservletrequest request, httpservletresponse response, filterchain chain)
            throws servletexception, ioexception {
        final string authorizationheader = request.getheader("authorization");
        string username = null;
        string jwt = null;
        if (authorizationheader != null && authorizationheader.startswith("bearer ")) {
            jwt = authorizationheader.substring(7);
            username = jwtutil.extractusername(jwt);
        }
        if (username != null && securitycontextholder.getcontext().getauthentication() == null) {
            userdetails userdetails = userdetailsservice.loaduserbyusername(username);
            if (jwtutil.validatetoken(jwt, userdetails.getusername())) {
                usernamepasswordauthenticationtoken usernamepasswordauthenticationtoken = new usernamepasswordauthenticationtoken(
                        userdetails, null, userdetails.getauthorities());
                usernamepasswordauthenticationtoken
                        .setdetails(new webauthenticationdetailssource().builddetails(request));
                securitycontextholder.getcontext().setauthentication(usernamepasswordauthenticationtoken);
            }
        }
        chain.dofilter(request, response);
    }
}

5. 创建认证和授权接口

创建一个authenticationcontroller类,用于处理用户登录和生成jwt。

import org.springframework.beans.factory.annotation.autowired;
import org.springframework.http.responseentity;
import org.springframework.security.authentication.authenticationmanager;
import org.springframework.security.authentication.badcredentialsexception;
import org.springframework.security.authentication.usernamepasswordauthenticationtoken;
import org.springframework.security.core.userdetails.userdetails;
import org.springframework.web.bind.annotation.*;
@restcontroller
@requestmapping("/api")
public class authenticationcontroller {
    @autowired
    private authenticationmanager authenticationmanager;
    @autowired
    private jwtutil jwtutil;
    @autowired
    private userdetailsservice userdetailsservice;
    @postmapping("/authenticate")
    public responseentity<?> createauthenticationtoken(@requestbody authenticationrequest authenticationrequest) throws exception {
        try {
            authenticationmanager.authenticate(
                    new usernamepasswordauthenticationtoken(authenticationrequest.getusername(), authenticationrequest.getpassword())
            );
        } catch (badcredentialsexception e) {
            throw new exception("incorrect username or password", e);
        }
        final userdetails userdetails = userdetailsservice.loaduserbyusername(authenticationrequest.getusername());
        final string jwt = jwtutil.generatetoken(userdetails.getusername());
        return responseentity.ok(new authenticationresponse(jwt));
    }
}

6. 创建用户详情服务

创建一个userdetailsservice实现类,用于加载用户信息。

import org.springframework.beans.factory.annotation.autowired;
import org.springframework.security.core.userdetails.userdetails;
import org.springframework.security.core.userdetails.userdetailsservice;
import org.springframework.security.core.userdetails.usernamenotfoundexception;
import org.springframework.stereotype.service;
import java.util.arraylist;
@service
public class customuserdetailsservice implements userdetailsservice {
    @autowired
    private userrepository userrepository;
    @override
    public userdetails loaduserbyusername(string username) throws usernamenotfoundexception {
        user user = userrepository.findbyusername(username)
                .orelsethrow(() -> new usernamenotfoundexception("user not found with username: " + username));
        return new org.springframework.security.core.userdetails.user(user.getusername(), user.getpassword(), new arraylist<>());
    }
}

7. 配置application.properties

application.properties文件中配置jwt密钥。

jwt.secret=yoursecretkey

8. 测试

启动应用后,可以通过发送post请求到/api/authenticate接口进行登录,获取jwt。然后在请求头中添加authorization: bearer <token>,即可访问受保护的接口。

到此这篇关于spring boot集成jwt实现无状态认证与授权的文章就介绍到这了,更多相关spring boot jwt无状态认证与授权内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

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

发表评论

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