springboot后台开发记录————token的使用

springboot后台开发记录————token的使用

一、token的作用

session和token都是用来保持会话,功能相同;
而在前后端分离的项目中,使用token能够降低服务器压力,登录成功后,服务端会在响应主体中将{token:‘字符串’}返回给客户端。客户端通过cookie、sessionStorage、localStorage都可以进行存储。再次请求时不会默认携带,需要在请求拦截器位置给请求头中添加认证字段Authorization携带token信息,服务器端就可以通过token信息查找用户登录状态。

二、设置拦截器

在springboot中设置要拦截的路径,除了登录以外,其他的请求全部都要在请求头里携带token

1、拦截请求

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ReqInterceptor()).addPathPatterns("/**")
                .excludePathPatterns("/auth/login");
    }
}

拦截除登录以外的路径

2、自定义Token工具类

token实际上是对信息进行加密后的一串字符串,token里面一般包含的信息有用户相关信息,创建时间,存活时间等,这些信息在解码token时能够判断token属于谁以及是否过期等

先引入依赖

        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>

TokenUtil.java
里面封装了两种创建token的方法和解析token的方法


import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TokenUtil {

    /****
     * 默认为10天的token
     * @param uid
     * @param openid
     * @return
     */
    public static String createToken(String uid,String openid){
        String token;
        token= JWT.create().withClaim("uid",uid)
                .withClaim("generatetime",System.currentTimeMillis())
                .withClaim("exptime",1000*1*60*60*24*10)//设置token过期时间为10天
                .sign(Algorithm.HMAC256(openid));
        return token;
    }

    /****
     * 自定义有效时长的token
     * @param uid
     * @param account
     * @param liveTime
     * @return
     */
    public static String createToken(String uid,String account,Long liveTime){
        String token;
        token= JWT.create().withClaim("uid",uid)
                .withClaim("generatetime",System.currentTimeMillis())
                .withClaim("exptime",liveTime)//设置token过期时间为10天
                .sign(Algorithm.HMAC256(account));
        return token;
    }
    /****
     * 返回参数
     * true:toke有效
     * false:token无效
     * @param token
     * @return
     */
    public static boolean decodeToken(String token){
        Long currentTime = System.currentTimeMillis();
        try {
            Long generateTime = JWT.decode(token).getClaim("generatetime").asLong();
            Long expTime = JWT.decode(token).getClaim("exptime").asLong();
            if(currentTime - generateTime > expTime){
                return false;
            }
            else return true;
        }catch (Exception e){
            return true;
        }
    }
}

3、处理被拦截的请求

逻辑是将被拦截的请求中的头文件中的token取出来,进行解析,如果为空或者解析失败或者过期,则token为无效的token,访问将被拒绝,需要重新登录以获取token

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.program.facesigninsystem.entity.ResponseModel;
import net.sf.json.JSONObject;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Base64;

public class ReqInterceptor extends HandlerInterceptorAdapter {

        /**
         * 一个拦截器
         * @param request
         * @param response
         * @param handler
         * @return
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            //得到请求头
            String Authorization = request.getHeader("Authorization");//获得token
            String token = Authorization.substring(7);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            //如果token没有则返回
            if(token==null || token.length()==0){
                JSONObject jsonObject = JSONObject.fromObject(new ResponseModel(310, "无token,不允许访问!").toString());
                response.getWriter().append(jsonObject.toString()).flush();
                return false;
            }
            else {
                try{
                    Long currentTime = System.currentTimeMillis();
                    Long generateTime = JWT.decode(token).getClaim("generatetime").asLong();
                    Long expTime = JWT.decode(token).getClaim("exptime").asLong();
                    if(currentTime - generateTime > expTime) {
                        JSONObject jsonObject = JSONObject.fromObject(new ResponseModel(310, "token过期,请重新登录!").toString());
                        response.getWriter().append(jsonObject.toString()).flush();
                        return false;
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    //验证失败
                    JSONObject jsonObject = JSONObject.fromObject(new ResponseModel(310, "token无效,不允许访问!").toString());
                    response.getWriter().append(jsonObject.toString()).flush();
                    return false;
                }
            }
            return super.preHandle(request, response, handler);
        }
}

三、token的颁发

import com.program.facesigninsystem.entity.ResponseModel;
import com.program.facesigninsystem.entity.UserInfo;
import com.program.facesigninsystem.service.IUserInfoService;
import com.program.facesigninsystem.util.HttpClient;
import com.program.facesigninsystem.util.TokenUtil;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Random;

@CrossOrigin
@RestController
@RequestMapping(value = "/auth")
public class UserController {
    final private String APP_ID = "******************";
    final private String SECRET = "*****************************";

    @Autowired
    IUserInfoService iUserInfoService;
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    private ResponseModel loginUser(@RequestBody JSONObject account){
        ResponseModel responseModel;
        String openid = "";
        try{
            openid = HttpClient.getWxUserOpenid(account.get("code").toString(),APP_ID,SECRET).get("openid").toString();
        }catch (Exception e){
            responseModel = new ResponseModel(199,"微信授权失败");
            return responseModel;
        }
        UserInfo userInfo = iUserInfoService.loginUser(openid);
        if(userInfo!=null) {
            //判断该用户token是否为空
            if(userInfo.getToken()==null||userInfo.getToken().equals("")){
                String token = TokenUtil.createToken(userInfo.getUid(),userInfo.getOpenid(),1000*60l);
                userInfo.setToken(token);
                iUserInfoService.updateToken(userInfo.getUid(),token);//token存入用户数据库
            }
            else{
                if(!TokenUtil.decodeToken(userInfo.token)){
                    String token = TokenUtil.createToken(userInfo.getUid(),userInfo.getOpenid());
                    userInfo.setToken(token);
                    iUserInfoService.updateToken(userInfo.getUid(),token);//token存入用户数据库
                }
            }
            responseModel = new ResponseModel(200,"登录成功",userInfo);
        }
        else{
            String uid = "";
            Random random = new Random();
            for (int i = 0; i < 20; i++) {
                uid += String.valueOf(random.nextInt(10));
            }
            userInfo = new UserInfo();
            String token = TokenUtil.createToken(uid,openid);
            userInfo.setToken(token);
            userInfo.setUid(uid);
            userInfo.setOpenid(openid);
            iUserInfoService.addUser(uid,openid,token);
            responseModel = new ResponseModel(200,"登录成功",userInfo);
        }
        return responseModel;
    }
}

这个接口是对微信登录的验证,着重来看逻辑的处理:
用户登录发起登录请求时,判断数据库中是否存在该用户:
1、如果不存在,则创建该用户,将用户相关信息以及token创建时间和存活时间存于token中,并为其颁发token,同时存于数据库中,并将token和相关信息返回;
2、如果存在该用户,则对该用户的token进行解析:
(1)如果token已经过期,则颁发新的token,同时存于数据库,并将token和相关信息返回
(2)如果token有效,则直接将token和相关信息返回

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值