当前位置: 代码网 > it编程>编程语言>Java > SpringBoot整合JWT实现Token认证与自动刷新

SpringBoot整合JWT实现Token认证与自动刷新

2026年07月20日 Java 我要评论
session 方式在分布式环境下不好用,jwt(json web token)是目前主流的无状态认证方案。服务端不需要存 session,token 中包含了用户信息。一、jwt 结构header.

session 方式在分布式环境下不好用,jwt(json web token)是目前主流的无状态认证方案。服务端不需要存 session,token 中包含了用户信息。

一、jwt 结构

header.payload.signature

header: 加密算法
payload: 用户数据(不要放密码)
signature: 签名,防止篡改

二、jwt 工具类

@component
public class jwtutil {

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

    @value("${jwt.expire:86400000}")
    private long expire;  // 默认24小时

    public string generatetoken(long userid, string username) {
        date now = new date();
        return jwts.builder()
            .setsubject(userid.tostring())
            .claim("username", username)
            .setissuedat(now)
            .setexpiration(new date(now.gettime() + expire))
            .signwith(signaturealgorithm.hs256, secret)
            .compact();
    }

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

    public boolean validatetoken(string token) {
        try {
            parsetoken(token);
            return true;
        } catch (exception e) {
            return false;
        }
    }
}

三、登录接口

@restcontroller
@requestmapping("/auth")
public class authcontroller {

    @autowired
    private jwtutil jwtutil;

    @postmapping("/login")
    public resultvo<map<string, object>> login(
            @requestparam string username,
            @requestparam string password) {
        // 校验用户名密码
        if (!"admin".equals(username) || !"123456".equals(password)) {
            return resultvo.error(401, "用户名或密码错误");
        }

        // 生成 token
        string accesstoken = jwtutil.generatetoken(1001l, username);
        string refreshtoken = jwtutil.generaterefreshtoken(1001l);

        map<string, object> result = new hashmap<>();
        result.put("accesstoken", accesstoken);
        result.put("refreshtoken", refreshtoken);
        result.put("expiresin", 86400);

        return resultvo.success(result);
    }
}

四、token 刷新

@postmapping("/refresh")
public resultvo<map<string, object>> refresh(
        @requestparam string refreshtoken) {
    if (!jwtutil.validatetoken(refreshtoken)) {
        return resultvo.error(401, "refreshtoken 无效");
    }

    claims claims = jwtutil.parsetoken(refreshtoken);
    long userid = long.parselong(claims.getsubject());
    string username = claims.get("username", string.class);

    string newaccesstoken = jwtutil.generatetoken(userid, username);
    string newrefreshtoken = jwtutil.generaterefreshtoken(userid);

    return resultvo.success(map.of(
        "accesstoken", newaccesstoken,
        "refreshtoken", newrefreshtoken
    ));
}

五、拦截器校验

@component
public class jwtinterceptor implements handlerinterceptor {

    @autowired
    private jwtutil jwtutil;

    @override
    public boolean prehandle(httpservletrequest request,
                             httpservletresponse response,
                             object handler) throws exception {
        string token = request.getheader("authorization");
        if (token == null || !token.startswith("bearer ")) {
            throw new businessexception(401, "未登录");
        }

        token = token.substring(7);
        if (!jwtutil.validatetoken(token)) {
            throw new businessexception(401, "token 已过期");
        }

        // 将用户信息存入请求上下文
        claims claims = jwtutil.parsetoken(token);
        request.setattribute("userid", claims.getsubject());
        request.setattribute("username", claims.get("username"));

        return true;
    }
}

六、前端调用

// 登录
const resp = await fetch('/auth/login', {
    method: 'post',
    headers: {'content-type': 'application/json'},
    body: json.stringify({username: 'admin', password: '123456'})
});
const { accesstoken, refreshtoken } = await resp.json();

// 后续请求携带 token
fetch('/api/user', {
    headers: {'authorization': 'bearer ' + accesstoken}
});

// token 过期时用 refreshtoken 刷新
async function refreshaccesstoken() {
    const resp = await fetch('/auth/refresh', {
        method: 'post',
        body: new urlsearchparams({refreshtoken})
    });
    const data = await resp.json();
    accesstoken = data.accesstoken;
}

七、安全注意事项

// 1. jwt 中不要放敏感信息
claims claims = jwts.parser()
    .setsigningkey(secret)
    .parseclaimsjws(token)
    .getbody();
string password = claims.get("password");  // ❌ 错误!

// 2. 密钥不要写死,用配置中心或环境变量
@value("${jwt.secret}")
private string secret;

// 3. accesstoken 有效期短(15-30分钟)
// refreshtoken 有效期长(7天),专门用来刷新 accesstoken

总结

session 认证:服务端存 session,分布式下需要共享 session
jwt 认证: 无状态,token 携带用户信息,适合分布式

jwt 缺点:签发后无法主动失效(只能等过期)
解决方案:accesstoken 短时效 + refreshtoken 刷新机制

到此这篇关于springboot整合jwt实现token认证与自动刷新的文章就介绍到这了,更多相关springboot token认证与自动刷新内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

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

发表评论

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