zoukankan      html  css  js  c++  java
  • JWT前后端分离demo

    后端项目完整代码:https://github.com/shenweiquan/jwt-demo

    一:准备工作

      1-1 运行环境:

      后端:jdk1.8,springboot,jwt

      前端:vue , elementui

      1-2 创建前端和后端项目

      后端项目结构:

       

    二:重要的代码

      JwtUtil

    package com.swq.jwt.util;
    
    import com.alibaba.fastjson.JSONObject;
    import com.swq.jwt.dto.CheckResult;
    import com.swq.jwt.entry.User;
    import io.jsonwebtoken.*;
    import org.apache.tomcat.util.codec.binary.Base64;
    
    import com.swq.jwt.constant.Constant;
    
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import java.util.Date;
    
    public class JwtUtil {
    
        /**
         * 由字符串生成key
         *
         * @return
         */
        public static SecretKey generalKey() {
            String Strkey = Constant.JWT_SECRET;//自定义的字符串
    
            byte[] decode = Base64.decodeBase64(Strkey.getBytes());//解密
    
            //利用AES加密算法构造密匙
            SecretKey key = new SecretKeySpec(decode, 0, decode.length, "AES");
    
            return key;
        }
    
        /**
         * @param id      JWT的唯一标识
         * @param subject
         * @param ttl     过期时间长度
         * @return
         */
        public static String createJWT(
                String id,
                String subject,
                long ttl
        ) {
    
            long timeMillis = System.currentTimeMillis();//创建jwt时间
            Date date = new Date(timeMillis); //转换为日期
    
            JwtBuilder jwt = Jwts.builder()
                    .setId(id)  //jwt_id
                    .setIssuedAt(date) //创建时间
                    .setSubject(subject) //sub(Subject):代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串
                    .signWith(SignatureAlgorithm.HS256, generalKey());
    
            //设置过期时间
            if (ttl > 0) {
                long exp = timeMillis + ttl; //过期时间
                Date expDate = new Date(exp);
                jwt.setExpiration(expDate);//设置过期时间
    
            }
    
            return jwt.compact();
        }
    
        /**
         * 解密jwt
         * @param jwt
         * @return
         */
        public  static Claims parseJwt(String jwt)
        {
            SecretKey secretKey = generalKey();
    
            Claims body = Jwts.parser()
                    .setSigningKey(secretKey)
                    .parseClaimsJws(jwt).getBody();
    
            return body;
    
        }
    
        /**
         * 获得subject,转化为json字符串
         * @param user
         * @return
         */
        public static String generalSubject(User user)
        {
           return  JSONObject.toJSONString(user);
        }
    
        /**
         * 验证jwt
         */
        public static CheckResult vaildateJwt(String jtw)
        {
            CheckResult res = new CheckResult();
    
            Claims claims = null;
    
            try{
                claims = parseJwt(jtw);
                res.setSuccess(true);
                res.setClaims(claims);
            }
            catch (ExpiredJwtException e1) //过期异常
            {
                res.setSuccess(false);
                res.setErrcode(Constant.JWT_ERRCODE_EXPIRE);
            }
            catch (SignatureException e2) //签名异常
            {
                res.setSuccess(false);
                res.setErrcode(Constant.JWT_ERRCODE_FAIL);
            }
            catch (Exception e)
            {
                res.setSuccess(false);
                res.setErrcode(Constant.JWT_ERRCODE_FAIL);
            }
    
    
    
            return res;
        }
    }

      拦截器:

    package com.swq.jwt.config;
    
    import com.swq.jwt.Interceptor.interceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    /**
     * AJAX请求跨域
     * @author Mr.W
     * @time 2018-08-13
     */
    
    
    @Configuration
    public class CorsConfig extends WebMvcConfigurerAdapter {
        static final String ORIGINS[] = new String[] { "GET", "POST", "PUT", "DELETE" };
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods(ORIGINS)
                    .maxAge(3600);
        }
    
        //拦截器
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
          registry.addInterceptor(new interceptor())
                  .addPathPatterns("/**")//需要拦截的url
                  .excludePathPatterns("/user/login");//不需要拦截的url
    
        }
    }
    package com.swq.jwt.Interceptor;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.swq.jwt.dto.CheckResult;
    import com.swq.jwt.exception.TokenException;
    import com.swq.jwt.util.JwtUtil;
    import io.jsonwebtoken.Claims;
    import org.apache.tomcat.jni.User;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    @Component
    public class interceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
    
    
            String token = request.getHeader("Authorization");
    
            if(token == null || token.equals(""))
            {
                    throw  new TokenException("token is null");
            }
    
            CheckResult checkResult = JwtUtil.vaildateJwt(token);
    
            if(checkResult.isSuccess()) //验证成功
            {
                Claims claims = checkResult.getClaims();
                String subject = claims.getSubject();
                JSONObject parse = JSONObject.parseObject(subject);
                User user = JSON.toJavaObject(parse, User.class);
    
                return true;
            }
            else
            {
                throw  new TokenException("token parse fail");
            }
    
    
        }
    }
    Constant:
    package com.swq.jwt.constant;
    
    /**
     * 常量类
     */
    public class Constant {
    
    
    
    
        //异常
        public static final String JWT_ERRCODE_EXPIRE="token is expire";
        public static final String JWT_ERRCODE_FAIL="unkonw error";
    
    
        //jwt需要用到的常量
        public static final String JWT_ID = "SWQ-1998"; //jwt签发者
        //密匙
        public static final String JWT_SECRET = "nfjenfaEINFUNSEFUNBFninwdw";//随便写个,注意长度必须大于16
        //过期时间
        public static final int JWT_TTL = 60 *60 *1000;
    
    }

    前端封装axios:

    //引入安装的axios插件
    import axios from 'axios'
    
    /****** 创建axios实例 ******/
    const service = axios.create({
      //baseURL: process.env.BASE_URL,  // api的base_url
      timeout: 5000  // 请求超时时间
    });
    
    service.interceptors.request.use(
      config => {
        if (sessionStorage.getItem('token')) {  // 判断是否存在token,如果存在的话,则每个http header都加上token
          config.headers.Authorization = sessionStorage.getItem('token');
        }
        return config;
      },
      err => {
        return Promise.reject(err);
      });
    
     export default service

    登录成功后,后台返回token,前端保存

    <template>
      <div style="20%;margin:0 auto">
    
    
    
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>登录</span>
      </div>
      <div class="text item">
       <el-input v-model="name" placeholder="请输入昵称"></el-input>
            <p></p><p></p>
            <el-input placeholder="请输入密码" v-model="password" show-password></el-input>
      </div>
      <p></p><p></p>
      <el-button @click="login">登录</el-button>
    </el-card>
    
    
      </div>
    </template>
    
    <script>
    import service from '@/request/http'
    
    export default {
      data: function() {
        return {
          name:'',
          password: ''
        }
      },
    
      methods:{
        login(){
    
            service({
              method:'post',
              url:'/user/login',
              data:{
                name:this.name,
                password:this.password
              }
            })
            .then(res =>{
    
              if(res.data.success == true)
              {
                  sessionStorage.setItem('token',res.data.data) //保存token
                  //跳转到首页
                  this.$router.push('/index')//进入主页
              }
              else
              {
    
                  this.$message.success(res.data.msg);
              }
    
            })
        }
      }
    }
    </script>
  • 相关阅读:
    Python——python读取html实战,作业7(python programming)
    Python——python读取html实战,作业7(python programming)
    Python——python读取xml实战,作业6(python programming)
    Python——python读取xml实战,作业6(python programming)
    二分查找(c &amp; c++)
    大型站点技术架构(八)--站点的安全架构
    Android MTP 文件浏览Demo
    HDU2037 事件排序问题
    折腾开源WRT的AC无线路由之路-3
    启动VIP报CRS-1028/CRS-0223致使VIP状态为UNKNOWN故障分析与解决
  • 原文地址:https://www.cnblogs.com/swqblog/p/12851975.html
Copyright © 2011-2022 走看看