zoukankan      html  css  js  c++  java
  • Springboot前后端分离中,后端拦截器拦截后,前端没有对应的返回码可以判断

    项目登录流程如下

           用户进入前端登录界面,输入账号密码等,输入完成之后前端发送请求到后端(拦截器不会拦截登录请求),后端验证账号密码等成功之后生成Token并存储到数据库,数据库中包含该Token过期时间,然后返回生成的Token到前端。

           前端收到Token,表示登录成功,把这个Token存储到浏览器Cookie中。然后跳转到用户中心页面,用户中心页面从浏览器Cookie中扣出Token,跟随请求用户数据接口一起带到后端。

           后端通过拦截器拦截到这个请求,去判断这个Token是否有效,有效就放过去做他该做的事情,无效就抛出异常。

    跨域配置

    先说一下这个前后分离的项目,已经配置过跨域这些问题。我这里后端配置的方式如下:

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                    .maxAge(3600)
                    .allowCredentials(true);
        }
    }

    前端每次发送请求也都有在ajax里面设置xhrFields:{withCredentials: true}属性。

    拦截器代码

    @Component
    public class LoginInterceptor extends HandlerInterceptorAdapter {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            //从header中获取token
            String token = request.getHeader("token");
            //token为空
            if(StringUtils.isBlank(token)){
                throw new XjxccException("登录信息不存在,请重新登录", 601);
            }
    
            //查询token信息
            TbUserToken tbToken = tokenService.queryByToken(token);
            if(tbToken == null || tbToken.getExpireTime().getTime() < System.currentTimeMillis()){
                throw new XjxccException("登录信息已失效,请重新登录", 602);
            }
    
            return true;
        }
    }

    问题

    现在的情况是,如果Token正常就没问题,如果Token失效了,前端发送的请求就会提示跨域问题,可是该项目已经配置过跨域问题了。既然又提示跨域问题,那我们修改代码如下:

    @Component
    public class LoginInterceptor extends HandlerInterceptorAdapter {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            //从header中获取token
            String token = request.getHeader("token");
            //token为空
            if(StringUtils.isBlank(token)){
                setCorsMappings(request, response);
                throw new XjxccException("登录信息不存在,请重新登录", 601);
            }
    
            //查询token信息
            TbUserToken tbToken = tokenService.queryByToken(token);
            if(tbToken == null || tbToken.getExpireTime().getTime() < System.currentTimeMillis()){
                setCorsMappings(request, response);
                throw new XjxccException("登录信息已失效,请重新登录", 602);
            }
    
            return true;
        }
    
        private void setCorsMappings(HttpServletRequest request, HttpServletResponse response){
            String origin = request.getHeader("Origin");
            response.setHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
            response.setHeader("Access-Control-Allow-Credentials", "true");
        }
    }

     这样修改之后,如果Token无效,前端发送的请求就不会提示跨域问题。而且也可以在ajax的success方法中根据错误码(601/602)做不同的判断,代码如下:

    $.ajax({
        type: "POST",
        url: "请求用户信息接口",
        xhrFields:{withCredentials: true},
        headers: {token: vm.token},
        contentType: 'application/json',  
        success: function(result){
                    //如果是token无效
            if(result.code == 601 || result.code == 602){
                layer.msg(result.msg + "<br>稍后为您自动跳转到登录页面");
                window.setInterval(function (){
                    window.location.href = "user-login.html";
                },1500);
            }else if(判断用户信息接口返回的code){
                        ...
                    }
        },error: function(){
            layer.msg("系统异常");
        }
    });

    下面附上上面代码中的XjxccException类:

    /**
     * <p>Title: XjxccException.java</p>  
     * <p>Description: 自定义异常</p>  
     * <p>Copyright: Copyright (c) 2018</p>
     *  
     * @email lgqxjxcc@163.com 
     * @author liguoqing  
     * @date 2018年10月21日  
     * @version 1.0
     */
    public class XjxccException extends RuntimeException {
        private static final long serialVersionUID = 1L;
        
        private String msg;
        private int code = 500;
        
        public XjxccException(String msg) {
            super(msg);
            this.msg = msg;
        }
        public XjxccException(String msg, Throwable e) {
            super(msg, e);
            this.msg = msg;
        }
        public XjxccException(String msg, int code) {
            super(msg);
            this.msg = msg;
            this.code = code;
        }
        public XjxccException(String msg, int code, Throwable e) {
            super(msg, e);
            this.code = code;
        }
        public String getMsg() {
            return msg;
        }
        public void setMsg(String msg) {
            this.msg = msg;
        }
        public int getCode() {
            return code;
        }
        public void setCode(int code) {
            this.code = code;
        }
    }
  • 相关阅读:
    VS2010中ActiveX控件"未能实例化activex控件 因为这需要设计时授权"解决办法
    CreateThread,_beginthread与AfxbeginThread之间的区别
    C的定时器timeSetEvent使用
    GetCurrentTime(),GetLocalTime(),GetSystemTime()之间的区别
    使用PostThreadMessage在Win32线程间传递消息
    c++配置文件.ini,GetPrivateProfileString( )WritePrivateProfileString( )
    Callback函数详解
    Dispose,using
    mysql 存储过程,表
    函数,视图,存储过程,触发器,sysobjects (系统对象表),事务,异常
  • 原文地址:https://www.cnblogs.com/kawhileonardfans/p/10966880.html
Copyright © 2011-2022 走看看