基于spring-boot的token登录验证

1.什么是token

用百度百科的话说就是密令的意思,通俗的来讲就是打开密码锁的钥匙.它其实就是一串很长的字符串(由3段字符串组成,具体哪3段后面说).

2.token是干什么的

token的出现是为了解决用户在登录时需要频繁去数据库读取用户信息来作验证而给数据库带来的巨大压力.相信大家看到这里比较懵,究竟他是怎么解决的呢!上面说了token由3部分组成,头部(header),载荷(playload)和签证(signature).在用户初次登录时,前端设置token默认为空,这时候根据用户的姓名,密码,过期时间等通过加密生成token存入数据库,并返回给前端,以后每次发起请求时request都会带着返回的token访问服务器,服务器解码后判断该token是否过期等相应的操作,这样一来就减少了数据库的访问压力.(如果还有懵逼的朋友,请谅解我的表达能力,继续往下看!!!)

3.token的组成

上面我们说了token由3部分组成.下面我们看看是哪3部分

(1).头部(header)

这部分组成很简单

typ:生成的密钥(token)的类型,我们这里用jwt(json web token)

alg:生成密钥的加密算法,我们这用HS256

例如:

{
“typ” : “JWT”,
“alg” : “HS256”
}

(2).载荷(playload)

这部分就比较复杂了,用来存放有效信息

一般由3部分组成
1.标准注册的说明
2.公共的说明
3.私有的声明

标准注册的声明(需要什么就用什么)

iss:jwt签发者

sub:jwt所面向的用户

aud:接受jwt的一方

exp:jwt的过期时间必须要大于签发时间

nbf:定义在什么时间之前,该jwt是不可用的

jti:jwt的唯一身份标识,主要用来作为一次性token

列如

{
“name”:“张三”,
“age”:“23”,
“company”:“小米”
}

(3)签证消息(signature)

这部分由3小部分构成
header(加密后的)
playload(加密后的)
secret(密钥)

好了token的组成也大概介绍完了,下面就介绍如何搭建demo了.

基于boot的token登录

第一步:先引入jwt的依赖

<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.0</version>
</dependency>

第二步:配置我们需要的参数

server:
  port: 8088 //这是Tomcat的端口号
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver  //这里是数据库驱动
    url: //这是数据库的url,注意mysql5.0版本要加时区(serverTimezone=CTT),否则报错
    username: //数据库名称
    password: //该数据库密码
mybatis:
  mapper-locations: //mybatis的mapper路径 classpath:
  type-aliases-package: //要映射的包的别名
  configuration:
    map-underscore-to-camel-case: false

第三步:编写我们的mapper映射文件

<?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.hongsi.tokenlogin.dao.UserDao">
    <insert id="insert" parameterType="user">
        insert into user(name,passwd,username,token) values(#{name},#{passwd},#{username},#{token})
    </insert>
    <select id="select" parameterType="user" resultType="user">
        select * from user where name = #{name}
    </select>
    <update id="update" parameterType="user">
        update user set token=#{token} where id = #{id}
    </update>
</mapper>

第四步:编写我们的实体类

import lombok.Data;

@Data
public class User {
    private String name;
    private String username;
    private String passwd;
    private String token;
    private Integer id;
}
//@Data是由lombok提供的方法,可以自动生成set,get,toString等方法

第五步:编写我们的mybatis的dao接口

@Mapper
public interface UserDao {
    public void insert(User user);
    public User select(User user);
    public void update(User user);
}
//注意一定要加@Mapper注解,否则mapper文件找不到改接口

第六步:编写我们的工具类(用来生成token和解密token的)

@Component
public class JwtToken {
    //设置一个密钥,用来服务端验证token
//    public final String secret = "ilovechina";
    public String createToken(User user,String secret){
//        String secret = "ilovechina";
        //iatDate:签发时间
        Date iatDate = new Date();
        //expDate:过期时间
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.MINUTE,3);
        Date expDate = nowTime.getTime();
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("typ","JWT");
        map.put("alg","HS256");
        //生成token
        String token = JWT.create().withHeader(map)
                .withClaim("name",user.getName())
                .withClaim("passwd",user.getPasswd())
                .withClaim("username",user.getPasswd())
                .withExpiresAt(expDate)
                .withIssuedAt(iatDate)
                .sign(Algorithm.HMAC256(secret));
        System.out.println(token);
        return token;
        }
        //token解密
        public Map<String,Claim> verifyToken(String token,String secret){
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret)).build();
            DecodedJWT decodedJWT = verifier.verify(token);
            return decodedJWT.getClaims();
        }
}
//注意要加@Component注解,将该工具类注入到beanFactory中

第七步:开始我们的核心controller的编写
建议大家有时间的还是按mvc的模式来写这个demo,养成良好的编码习惯,小编比较忙就直接上controller了

@RestController
@RequestMapping("/user")
public class LoginController {
    @Resource
    private UserDao userDao;
    @Resource
    private JwtToken jwtToken;

    @RequestMapping("/login")
    public String login(@RequestBody User user, HttpServletRequest request){
        String secret = "ilovechina";//自定义密玥
        String token = request.getHeader("token");//获取请求头中携带的token
        //对获取的token进行判断,是否为空,为空则重新登录
        if (token == null || token.length() ==0 || token.equals("null")) {
            token = jwtToken.createToken(user,secret);//传入用户信息和密钥进行加密
            user.setToken(token);
            userDao.insert(user);//存入数据库
            return "登录成功!"+token;
        }
        Map<String,Claim> map = jwtToken.verifyToken(token,secret);//如果获取到的token不为空,则进行解密,加以判断
        String name = map.get("name").asString();
        user.setName(name);
        user = userDao.select(user);//根据token中用户名查找对应的密码,判断密码是否更改,更改则同步刷新token
        if(!user.getPasswd().equals(map.get("passwd").asString())){
            user.setToken(jwtToken.createToken(user,secret));
            userDao.update(user);
            return "您的密码已更改,系统已自动为您更新token!"+jwtToken.createToken(user,secret);
        }
        return "登录成功,无需重复登录!";
    }
}

建议把这些业务写在拦截器中,用拦截器拦截请求并验证token

下面贴出我的postman测试

当我们第一次登录时,token为我们设置的默认值null

在这里插入图片描述
此时登录成功,并返回token
在这里插入图片描述
这时我们用刚刚返回的token去测试
在这里插入图片描述
看到我们需要的效果了
在这里插入图片描述
此时当我们修改数据库中的密码时
在这里插入图片描述
再用刚刚生成的token去验证时,你会发现已经成功更新了token(数据库中也已更新,这里就不贴出来了)并返回给了前端,方便下一次的认证
在这里插入图片描述

好了,到这里token的简单登录就完成了,当然,我也阅读了几篇大佬的token文章,谢谢你们,现在我将我学到的及自己理解的传播下去.希望大家阅读后能有收获,当然随时欢迎大家指出我的错误,在下不甚感激,最后希望大家都能进步,在如今的互联网行业中,停下来也就被淘汰了,加油吧各位!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值