Springboot +JWT

本文详细介绍如何在SpringBoot中集成JWT实现登录权限保护。包括JWT的简介、生成与解析Token的工具类、自定义过滤器实现权限控制及示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要是springboot 集成 JWT来实现登录权限保护.

先简单介绍一下JWT:

JSON Web Token(JWT)是一个开放的标准(RFC 7519),它定义了一个紧凑且自包含的方式,用于在各方之间以JSON对象安全地传输信息。这些信息可以通过数字签名进行验证和信任。可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对来对JWT进行签名。
具体的JWT介绍可以查看官网:https://jwt.io/introduction/

 首先附上可以快速生成springboot项目的网址: https://start.spring.io/,当然也可以通过IDEA去生成一个springboot项目。

 其次是JWT官网提供的生成和解析Token 的链接: https://jwt.io/

 最后附上demo的地址:https://github.com/Jacob029049/JWT,有喜欢的朋友可以去clone

项目主要思路:1.login方法来获取Token ,然后把Token加到Header上

                         2.分别设置两个接口,filter过滤其中一个接口。来实现JWT权限的控制

 下面我贴上一些关键代码:

 1.登录获取Token,此处用户名密码写在配置文件里

    //login get token
    @RequestMapping("/login")
    public String Login(@RequestParam String username,@RequestParam String password){

        if (JWT_USER.equals(username) && JWT_PASSWORD.equals(password)){

            return jwtUtil.creatJwtToken();
        }
        return "NOK";
    }

  postman调用接口结果如下图:成功就返回Token

一个JWTToken 由 header,payload,signature三部分组成。

 2.下面是创建和解析JWTToken的Util工具类


import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

//jwt含有三部分:头部(header)、载荷(payload)、签证(signature)
/*
*(1)头部一般有两部分信息:声明类型、声明加密的算法(通常使用HMAC SHA256)
*(2)载荷该部分一般存放一些有效的信息。jwt的标准定义包含五个字段:
*    -iss:该JWT的签发者
    - sub: 该JWT所面向的用户
    - aud: 接收该JWT的一方
    - exp(expires): 什么时候过期,这里是一个Unix时间戳
    - iat(issued at): 在什么时候签发的

* (3)签证(signature) JWT最后一个部分。该部分是使用了HS256加密后的数据;包含三个部分:
* */

@Service("jwtUtil")
public class JWTUtil {

    private final Logger logger = Logger.getLogger(this.getClass().getName());

    @Value("${com.jwt.secret}")
    private  String SECRET;

    @Value("${com.jwt.issuer}")
    private  String JWT_ISSUER;

    public String creatJwtToken(){
        final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        final long nowMillis = System.currentTimeMillis();
        //设置过期时间
        final long ttlMillis = 5 * 60 * 100000;
        final long expMillis = nowMillis + ttlMillis;

        final Date now = new Date(nowMillis);
        final Date exp = new Date(expMillis);

        //Create the Signature SecretKey
        final byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(Base64.getEncoder().encodeToString(SECRET.getBytes()));
        final Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

        final Map<String, Object> headerMap = new HashMap<String, Object>();
        headerMap.put("alg", "HS256");
        headerMap.put("typ", "JWT");

        //add JWT Parameters
        final JwtBuilder builder = Jwts.builder()
                                        .setHeaderParams(headerMap)
                                        .setIssuedAt(now)
                                        .setExpiration(exp)
                                        .setIssuer(JWT_ISSUER)
                                        .signWith(signatureAlgorithm, signingKey);

        logger.info("JWT[" + builder.compact()+ "]");
        return builder.compact();

    }

    public Claims parseJWTToken(String token)
    {
        Claims claims = null;
        try
        {
            claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(SECRET)).parseClaimsJws(token)
                    .getBody();
        }
        catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | SignatureException
                | IllegalArgumentException e)
        {
            logger.info("Parse JWT errror " + e.getMessage());
            return null;
        }
        return claims;
    }
}
creatJwtToken() 主要是set Header(一般都是 alg:HS256,typ:JWT);set Claims(此处可以自定义,也可以用标准定义);sign(signatureAlgorithm,secretKey )secretKey是否要用base64再次编码看实际情况

需要在pom.xml里添加maven引用:
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
        </dependency>

3.自己实现的filter类的doFilter方法:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        //secretKey
        String SECRET = PropertyUtil.getProperty("com.jwt.secret","12345678");
        String JWT_ISSUER = PropertyUtil.getProperty("com.jwt.issuer","87654321");

        final byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(Base64.getEncoder().encodeToString(SECRET.getBytes()));

        //请求头上的token
        String jsonTokenWeb = request.getHeader(TOKEN_HEADER);

        HttpResponseBean responseWsBean = new HttpResponseBean();

        //exp 、iss、sign、 validate
        try {
            Claims claims = Jwts.parser().setSigningKey(apiKeySecretBytes).parseClaimsJws(jsonTokenWeb)
                    .getBody();
            String iss = Objects.isNull(claims.get("iss"))?null:String.valueOf(claims.get("iss"));
            if (!JWT_ISSUER.equals(iss)){
                setResponseWsBean(responseWsBean, HTTP_STATUS_ERROR, HTTP_TOKEN_MESSAGE_INVALID + "issuer is incorrect. ");
                response.getWriter().write(JSONObject.fromObject(responseWsBean).toString());
            }else{
                //validate pass
                filterChain.doFilter(request,response);
            }
        }catch (Exception e){
            logger.info("parse jwttoken error :"+ e.getMessage());
            setResponseWsBean(responseWsBean, HTTP_STATUS_ERROR, HTTP_TOKEN_MESSAGE_INVALID + e.getMessage());
            response.getWriter().write(JSONObject.fromObject(responseWsBean).toString());
        }

    }

主要是获取header上的Token信息,然后进行解析来判断时间,签名等是否一致,当然自定义的用户权限需要自己去判断,如果有权限就放行,不行的话就返回response到接口。

4.最后接口进行验证,此处我设置的url过滤的是(/home/*)

(1) http://localhost:8081/hello/welcome 返回结果正常,无论加不加header Token

(2) http://localhost:8081/home/welcome 没有添加token情况:(此处Token添加后,如若超过exp截止时间,或者签名被他人修改等,也会返回错误)

(3) http://localhost:8081/home/welcome 添加header Token情况,并且token验证有效

如果文中有什么错误,欢迎指出,以免更多的人被误导。谢谢。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值