在SpringBoot中实战token

理解使用Token

Token的组成

token三大组成:
1、header:头部信息
2、payload:存放自己想要的信息
3、sign:是为了防止恶意篡改数据

JWT的简单介绍

1、什么是jwt:
java web token (jwt)是目前最流行的跨域身份验证解决方案
在没有跨域和没有分布式的情况下,基本验证方式是通过将session_id存入cookie中,这样每次访问将session_id带入。
在这里插入图片描述还有一种方式是将session持久化,简单的说就是将session存到数据库中,这样的不好处就是持久层坏掉的话,整个认证系统都会死掉,但是现在很多项目用到了这个方式,将session存在redis中。
当然,我们次按在重点研究jwt,他的原理就是会话数据只保存在客户端,每次请求都会被发送到服务器,
在这里插入图片描述2、jwt的原则
现在服务端身份验证之后,生成一个验证数据传给用户,之后,当用户与服务器通信时,客户在请求中发回验证数据。
3、jwt的数据结构
验证数据是一个很长的字符串,他就是有我们之前说过的那三部分组成,header,负载和签名。

其中JWT头是一个源数据的json对象,如:


```java
{

"alg": "HS256",

"typ": "JWT"

}

``

alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。

有效负载也是一个json串。JWT指定七个默认字段供选择。

iss:发行人

exp:到期时间

sub:主题

aud:用户

nbf:在此之前不可用

iat:发布时间

jti:JWT ID用于标识该JWT

除以上默认字段外,我们还可以自定义私有字段,如下例:

{

"sub": "1234567890",

"name": "chongchong",

"admin": true

}

签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。

JWT的使用

jwt有很多jar包来让自己使用,不过还是自己写一个适合自己的最好不过了
现在我们使用springboot来 实现jwt
1、maven


redis.clients
jedis
3.0.0


org.springframework.boot
spring-boot-starter-web


org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.2

	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<scope>runtime</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>

	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>1.16.22</version>
	</dependency>
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>fastjson</artifactId>
		<version>1.2.54</version>
	</dependency> 
</dependencies>

2、写一个自定义纾解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthToken {
 
}

3、WebAppconfiguration

@Configuration
public class WebAppConfiguration implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TokemInterceptor()).addPathPatterns("/**");
    }
}

4、创建拦截器
现在就是核心实现点了


```java
public class TokemInterceptor implements HandlerInterceptor {
	
	 Logger log = LoggerFactory.getLogger(TokemInterceptor.class);
 
    //存放鉴权信息的Header名称,默认是Authorization
    private String Authorization = "Authorization";
 
    //鉴权失败后返回的HTTP错误码,默认为401
    private int unauthorizedErrorCode = HttpServletResponse.SC_UNAUTHORIZED;
 
    /**
     * 存放用户名称和对应的key
     */
    public static final String USER_KEY = "USER_KEY";
 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
 
        //验证token
        if (method.getAnnotation(AuthToken.class) != null || handlerMethod.getBeanType().getAnnotation(AuthToken.class) != null) {
            String token = request.getParameter(Authorization);
            log.info("获取到的token为: {} ", token); 
            //此处主要设置你的redis的ip和端口号,我的redis是在本地
			Jedis jedis = new Jedis("127.0.0.1", 6379);
			 String username = null;
            if (token != null && token.length() != 0) {
            	//从redis中根据键token来获取绑定的username
                username = jedis.get(token);
                log.info("从redis中获取的用户名称为: {}", username);
            }
             //判断username不为空的时候
            if (username != null && !username.trim().equals("")) {
            	String startBirthTime = jedis.get(token + username);
                log.info("生成token的时间为: {}", startBirthTime);
                Long time = System.currentTimeMillis() - Long.valueOf(startBirthTime);
                log.info("token存在时间为 : {} ms", time);
                //重新设置Redis中的token过期时间
                if (time > CommonUtil.TOKEN_RESET_TIME) {
                    jedis.expire(username, CommonUtil.TOKEN_EXPIRE_TIME);
                    jedis.expire(token, CommonUtil.TOKEN_EXPIRE_TIME);
                    log.info("重置成功!");
                    Long newBirthTime = System.currentTimeMillis();
                    jedis.set(token + username, newBirthTime.toString());
                }
 
                //关闭资源
                jedis.close();
                request.setAttribute(USER_KEY, username);
                return true;
            } else {
                JSONObject jsonObject = new JSONObject();
 
                PrintWriter out = null;
                try {
                    response.setStatus(unauthorizedErrorCode);
                    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
 
                    jsonObject.put("code", ((HttpServletResponse) response).getStatus());
                    //鉴权失败后返回的错误信息,默认为401 unauthorized
                    jsonObject.put("message", HttpStatus.UNAUTHORIZED);
                    out = response.getWriter();
                    out.println(jsonObject);
 
                    return false;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (null != out) {
                        out.flush();
                        out.close();
                    }
                }
 
            }
 
        }
 
        request.setAttribute(USER_KEY, null);
 
        return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
 
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
 
    }
    }
最后,在登录的时候添加token信息,在其他接口添加Token注解
下次我们实战一个非常棒的案例。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值