当前位置: 代码网 > it编程>编程语言>Java > Java实现JWT登录认证的示例代码

Java实现JWT登录认证的示例代码

2025年04月03日 Java 我要评论
什么是jwt?jwt(json web token),简单来说就是:web领域中基于json格式的令牌。是最常用的令牌规范。第一部分:header(头),指定了令牌的签名算法、令牌类型。第二部分:pa

什么是jwt?

jwt(json web token),简单来说就是:web领域中基于json格式的令牌。是最常用的令牌规范。

  • 第一部分:header(头),指定了令牌的签名算法、令牌类型。
  • 第二部分:payload(有效载荷),使用base64来编码的,不是加密算法,能够解码。因此,该部分不适合存放用户的私密信息(如:密码)。
  • 第三部分:signature(签名),将第一部分和第二部分通过密钥加密得到。

在这里插入图片描述

解析token可以根据第三部分解密得到前两部分的信息,再比对前端传来的用户信息,完成校验。

token验证失败的情况?

token过期

密钥不正确

篡改了头部、载荷等

为什么需要令牌?

  • 承载了一定的数据信息,减少数据库访问次数
  • 具有一定的防伪功能

如何实现?

该部分代码不需要硬记,理解后直接使用即可。

添加依赖:

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

jwtutils.java(生成、解析token的工具类)

public class jwtutil {

    /**
     * 生成token
     * @param secretkey
     * @param ttlmillis
     * @param claims
     * @return
     */
    public static string createtoken(string secretkey, long ttlmillis, map<string, object> claims) {
        // 指定签名的时候使用的签名算法,也就是header那部分
        signaturealgorithm signaturealgorithm = signaturealgorithm.hs256;

        // 生成token的过期时间
        long expmillis = system.currenttimemillis() + ttlmillis;
        date exp = new date(expmillis);

        // 设置jwt的body
        jwtbuilder builder = jwts.builder()
                // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
                .setclaims(claims)
                // 设置签名使用的签名算法和签名使用的秘钥
                .signwith(signaturealgorithm, secretkey.getbytes(standardcharsets.utf_8))
                // 设置过期时间
                .setexpiration(exp);

        return builder.compact();
    }

    /**
     * 解析token
     * @param secretkey
     * @param token
     * @return
     */
    public static claims parsetoken(string secretkey, string token) {
        // 得到defaultjwtparser
        claims claims = jwts.parser()
                // 设置签名的秘钥
                .setsigningkey(secretkey.getbytes(standardcharsets.utf_8))
                // 设置需要解析的jwt
                .parseclaimsjws(token).getbody();
        return claims;
    }
 }

jwt配置:

application.yaml:

user:
  jwt:
    # 设置jwt签名加密时使用的秘钥
    user-secret-key: xxx
    # 设置jwt过期时间
    user-ttl: 7200000
    # 设置前端传递过来的令牌名称
    user-token-name: token

jwtproperties:

@component
@configurationproperties(prefix = "user.jwt")
@data
public class jwtproperties {

    private string usersecretkey;
    private long userttl;
    private string usertokenname;
}

jwtclaimsconstant(管理常量):

public class jwtclaimsconstant {
    public static final string user_id = "userid";
}

jwt拦截器:

@component
@slf4j
public class jwtinterceptor implements handlerinterceptor {

    @resource
    private jwtproperties jwtproperties;

    @override
    public boolean prehandle(httpservletrequest request, httpservletresponse response, object handler) throws exception {
        //1. 获取用户信息
        string token = request.getheader(jwtproperties.getusertokenname());
        //2. 判断用户信息是否有效,存入threadlocal
        try {
            claims claims = jwtutil.parsetoken(jwtproperties.getusersecretkey(), token);
            string userinfo = claims.get(jwtclaimsconstant.user_id).tostring();

            if (strutil.isnotblank(userinfo)){
                usercontext.setuser(long.valueof(userinfo));
            }

            //3. 放行
            return true;
        }catch (exception e){
            //4. 不通过
            response.setstatus(401);
            return false;
        }

    }

    @override
    public void aftercompletion(httpservletrequest request, httpservletresponse response, object handler, exception ex) throws exception {
        //清除用户信息
        usercontext.removeuser();
    }
}

webmvc配置(添加jwt拦截器)

@configuration
public class webconfig implements webmvcconfigurer {

    @resource
    private jwtinterceptor jwtinterceptor;

    @override
    public void addinterceptors(interceptorregistry registry) {
        registry.addinterceptor(jwtinterceptor)
                .addpathpatterns("/user/**")
                .excludepathpatterns("/user/user/login");
    }
}

usercontext(存储用户登录信息,方便其他业务需求获取)

public class usercontext {
    private static final threadlocal<long> threadlocal = new threadlocal<>();

    /**
     * 获取用户信息
     * @return
     */
    public static long getuser() {
        return threadlocal.get();
    }

    /**
     * 设置用户信息
     * @param userid
     */
    public static void setuser(long userid){
        threadlocal.set(userid);
    }

    /**
     * 移除用户信息
     */
    public static void removeuser(){
        threadlocal.remove();
    }
}

登录业务逻辑:

controller层:

@restcontroller
@requestmapping("/user/user")
@slf4j
public class usercontroller {

    @resource
    private userservice userservice;

    @postmapping("/login")
    public userloginvo login(@requestbody userlogindto userlogindto){
        log.info("用户登录:{}",userlogindto);
        return userservice.login(userlogindto);
    }
}

service层:

public interface userservice {
    userloginvo login(userlogindto userlogindto);
}
@service
@slf4j
public class userserviceimpl implements userservice {

    @resource
    private usermapper usermapper;

    @resource
    private jwtproperties jwtproperties;

    @override
    public userloginvo login(userlogindto userlogindto) {
        string username = userlogindto.getusername();
        string password = userlogindto.getpassword();
        //1. 校验用户名和密码
        userlogin userlogin = usermapper.getuserbyname(username);
        if (userlogin == null){
            throw new baseexception("用户名或密码错误");
        }
        password = digestutils.md5digestashex(password.getbytes());
        if (!password.equals(userlogin.getpassword())){
            throw new baseexception("用户名或密码错误");
        }

        //2. 生成token
        hashmap<string, object> claims = new hashmap<>();
        claims.put(jwtclaimsconstant.user_id, userlogin.getid());
        string token = jwtutil.createtoken(
                jwtproperties.getusersecretkey(),
                jwtproperties.getuserttl(),
                claims);

        //3. 封装vo
        userloginvo loginvo = userloginvo.builder()
                .token(token)
                .userid(userlogin.getid())
                .username(userlogin.getusername())
                .build();

        return loginvo;
    }
}

mapper层:

@mapper
public interface usermapper {
    userlogin getuserbyname(string username);
}
<?xml version="1.0" encoding="utf-8" ?>
<!doctype mapper public "-//mybatis.org//dtd mapper 3.0//en"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.user.mapper.usermapper">

    <select id="getuserbyname" resulttype="com.sky.user.pojo.entity.userlogin">
        select *
        from user_login where username = #{username} and is_delete = 0;
    </select>
</mapper>

其他关联代码:

@data
@allargsconstructor
@noargsconstructor
public class userlogindto {
    /**
     * 用户名
     */
    private string username;

    /**
     * 密码
     */
    private string password;

}
@data
@builder
@noargsconstructor
@allargsconstructor
public class userloginvo {
    private string token;
    private long userid;
    private string username;
}

测试:

登录接口:

在这里插入图片描述

其他接口:

在这里插入图片描述

在这里插入图片描述

到此这篇关于java实现jwt登录认证的示例代码的文章就介绍到这了,更多相关java jwt登录认证内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网! 

(0)

相关文章:

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

发表评论

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