美文网首页
vue+axios+springmvc身份验证

vue+axios+springmvc身份验证

作者: 以为是书生 | 来源:发表于2018-01-18 17:03 被阅读1897次

    后台用的是基于Token 的身份验证——JWT(json web token)

    1.maven 配置 在pom.xml 中加入如下代码

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

    2.新建JWT.java文件(此处我是放到com.demo.filter包下)

        package com.demo.filter;
    
        import com.auth0.jwt.JWTSigner;
        import com.auth0.jwt.JWTVerifier;
        import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper;
    
        import java.util.HashMap;
        import java.util.Map;
    
        public class JWT {
            private static final String SECRET = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW";
    
            private static final String EXP = "exp";
    
            private static final String PAYLOAD = "payload";
    
            //加密,传入一个对象和有效期
            public static <T> String sign(T object, long maxAge) {
                try {
                    final JWTSigner signer = new JWTSigner(SECRET);
                    final Map<String, Object> claims = new HashMap<String, Object>();
                    ObjectMapper mapper = new ObjectMapper();
                    String jsonString = mapper.writeValueAsString(object);
                    claims.put(PAYLOAD, jsonString);
                    claims.put(EXP, System.currentTimeMillis() + maxAge);
                    return signer.sign(claims);
                } catch(Exception e) {
                    return null;
                }
              }
    
            //解密,传入一个加密后的token字符串和解密后的类型
            public static<T> T unsign(String jwt, Class<T> classT) {
                final JWTVerifier verifier = new JWTVerifier(SECRET);
                try {
                    final Map<String,Object> claims= verifier.verify(jwt);
                    if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
                        long exp = (Long)claims.get(EXP);
                        long currentTimeMillis = System.currentTimeMillis();
                        if (exp > currentTimeMillis) {
                            String json = (String)claims.get(PAYLOAD);
                            ObjectMapper objectMapper = new ObjectMapper();
                            return objectMapper.readValue(json, classT);
                        }
                    }
                    return null;
                } catch (Exception e) {
                    return null;
                }
            }
        }
    

    3.登录时,生成token并传递给前台(ResponseData 类在页末贴出;此处不一定要像下面这种写法,关键是要看生成token那里)

        //处理登录
    @RequestMapping(value="/login.do", produces = "application/json; charset=utf-8")
    public @ResponseBody
    ResponseData login(String userName, String password, HttpServletRequest request, HttpServletResponse response) throws Exception{
        response.setCharacterEncoding("UTF-8");
        request.setCharacterEncoding("UTF-8");
        ResponseData responseData = ResponseData.ok();
        try{
            //先到数据库验证(这一步根据自己的代码逻辑来实现)
            User user = service.findUserByNameAndPassword(userName.trim(),CommUtil.generateMD5Str(password));
            if(null != user) {
                //给用户jwt加密生成token  这里是关键,生成了token 后,怎么给前台返回,那可以用你自己的方法;
                String token = JWT.sign(user, 60L* 1000L* 30L);
                //封装成对象返回给客户端
                responseData.putDataValue("token", token);
                responseData.putDataValue("user", user);
            }
            else{
                responseData =  ResponseData.customerError();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return responseData;
    }        
    

    4.写一个拦截;拦截访问的请求

        package com.demo.util;
    
        import com.alibaba.fastjson.JSONObject;
        import com.demo.bean.User;
        import com.demo.filter.JWT;
        import org.springframework.web.servlet.HandlerInterceptor;
        import org.springframework.web.servlet.ModelAndView;
    
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import java.io.PrintWriter;
    
        public class TokenInterceptor implements HandlerInterceptor {
            public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object handler, Exception arg3)
                    throws Exception {
            }
    
            public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView model) throws Exception {
            }
    
            //拦截每个请求
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
                response.setCharacterEncoding("utf-8");
                //此处是前台将token和loginId 放到了headers里面,后来来获取并处理
                String token = request.getHeader("X-Token");
                String loginId = request.getHeader("X-LoginId");
                ResponseData responseData = ResponseData.ok();
                //token不存在
                if(null != token) {
                    User user = JWT.unsign(token, User.class);
                    //解密token后的loginId与用户传来的loginId不一致,一般都是token过期
                    if(null != loginId && null != user) {
                        if(Integer.parseInt(loginId) == user.getId()) {
                            return true;
                        }
                        else{
                            responseData = ResponseData.forbidden();
                            responseMessage(response, response.getWriter(), responseData);
                            return false;
                        }
                    }
                    else
                    {
                        responseData = ResponseData.forbidden();
                        responseMessage(response, response.getWriter(), responseData);
                        return false;
                    }
                }
                else
                {
                    responseData = ResponseData.forbidden();
                    responseMessage(response, response.getWriter(), responseData);
                    return false;
                }
            }
    
            //请求不通过,返回错误信息给客户端
            private void responseMessage(HttpServletResponse response, PrintWriter out, ResponseData responseData) {
                responseData = ResponseData.forbidden();
                response.setContentType("application/json; charset=utf-8");
                String json = JSONObject.toJSONString(responseData);
                out.print(json);
                out.flush();
                out.close();
            }
        }
    

    5.spring-mvc.xml中配置拦截

         <mvc:interceptors>
              <mvc:interceptor>
                    <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
                    <mvc:mapping path="/**" />
                    <!-- /register.do 和 /login.do 不需要拦截(这里根据项目具体需求来配置)-->
                    <mvc:exclude-mapping path="/register.do" />
                    <mvc:exclude-mapping path="/login.do" />
                    <bean class="com.demo.util.TokenInterceptor"></bean>
              </mvc:interceptor>
        <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
        </mvc:interceptors>
    

    6.后台拦截已经做完,接下来是前端vue+axios 配置了

    在main.js中对axios进行配置

    import Vue from 'vue'
    import axios from 'axios'
    Vue.prototype.axios = axios
    // 请求时的拦截
    axios.interceptors.request.use(function (config) {
        // 发送请求之前做一些处理
        //在登录的时候,后台会将token和loginId传递过来,拿到值以后,用localStorage.setItem("jwt",JSON.stringify(data));存起来
        let storageData = localStorage.getItem("jwt");
        if(storageData){
            storageData = JSON.parse(storageData);
            let  token = storageData.token,
                 loginId = storageData.loginId;
            config.headers['X-Token'] = token;
            config.headers['X-LoginId'] = loginId;
        }
        return config;
      }, function (error) {
        // 当请求异常时做一些处理
        return Promise.reject(error);
      });
      // 响应时拦截
    axios.interceptors.response.use(function (response) {
        // 返回响应时做一些处理
        console.log("返回的数据",response);
        return response;
      }, function (error) {
        // 当响应异常时做一些处理
        return Promise.reject(error);
      });
    

    7.附上ResponseData 代码

        package com.demo.util;
    
        import java.util.HashMap;
        import java.util.Map;
    
        public class ResponseData {
            private final String message;
            private final int code;
            private final Map<String, Object> data = new HashMap<String, Object>();
    
            public String getMessage() {
                return message;
            }
    
            public int getCode() {
                return code;
            }
    
            public Map<String, Object> getData() {
                return data;
            }
    
            public ResponseData putDataValue(String key, Object value) {
                data.put(key, value);
                return this;
            }
    
            private ResponseData(int code, String message) {
                this.code = code;
                this.message = message;
            }
    
            public static ResponseData ok() {
                return new ResponseData(200, "Ok");
            }
    
            public static ResponseData notFound() {
                return new ResponseData(404, "Not Found");
            }
    
            public static ResponseData badRequest() {
                return new ResponseData(400, "Bad Request");
            }
    
            public static ResponseData forbidden() {
                return new ResponseData(403, "Forbidden");
            }
    
            public static ResponseData unauthorized() {
                return new ResponseData(401, "unauthorized");
            }
    
            public static ResponseData serverInternalError() {
                return new ResponseData(500, "Server Internal Error");
            }
    
           public static ResponseData customerError() {
                return new ResponseData(1001, "customer Error");
            }
        }
    

    相关文章

      网友评论

          本文标题:vue+axios+springmvc身份验证

          本文链接:https://www.haomeiwen.com/subject/sowioxtx.html