亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Springboot前后端分離項目配置跨域實現過程解析

 更新時間:2020年08月07日 10:31:47   作者:william_zhao  
這篇文章主要介紹了Springboot前后端分離項目配置跨域實現過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

項目登錄流程如下

用戶進入前端登錄界面,輸入賬號密碼等,輸入完成之后前端發(fā)送請求到后端(攔截器不會攔截登錄請求),后端驗證賬號密碼等成功之后生成Token并存儲到數據庫,數據庫中包含該Token過期時間,然后返回生成的Token到前端。

前端收到Token,表示登錄成功,把這個Token存儲本地。然后跳轉到用戶中心頁面,用戶中心頁面在ajax的請求頭中帶上Token,跟隨請求用戶數據接口一起帶到后端。

后端通過攔截器攔截到這個請求,去判斷這個Token是否有效,有效就放過去做他該做的事情,無效就拋出異常。

跨域配置

先說一下這個前后分離的項目,已經配置過跨域這些問題。我這里后端WebMvcConfig配置的方式如下:

import com.zdyl.devicemanagement.interceptor.AccessInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
  @Resource
  private WebServerConfig webServerConfig;

  @Bean
  public AccessInterceptor getAccessInterceptor() {
    return new AccessInterceptor();
  }

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    List<String> excludeUrl = new ArrayList<>();
    excludeUrl.add("/error");
    excludeUrl.add("/v1/zdyl/downloadFile");
    excludeUrl.add("/v1/zdyl/lcoStation/qrcode/**");
    excludeUrl.add("/devicemanagement/images/**/*");
    excludeUrl.add("/upgrade/**");
    excludeUrl.add("/v1/zdyl/login/**");
    excludeUrl.add("/NewsImage/**");
    excludeUrl.add("/v1/zdyl/equipment/alarm/toExcel/test");
    excludeUrl.add("/v1/zdyl/deviceMonitoring/get/alarm/toExcel/**");

    registry.addInterceptor(getAccessInterceptor()).addPathPatterns("/**")
        .excludePathPatterns(excludeUrl);
  }

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    List<String> locations = new ArrayList<String>();
    locations.add("classpath:/META-INF/resources/");
    locations.add("classpath:/resources/");
    locations.add("classpath:/public/");
    locations.add("file:" + webServerConfig.getUploadFileLocation());
    locations.add("file:" + webServerConfig.getPicpath());
    locations.add("file:" + webServerConfig.getProjectsource());

    String[] myArray = new String[locations.size()];
    registry.addResourceHandler("/**").addResourceLocations(locations.toArray(myArray));
  }

  @Bean
  public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
  }

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

前端每次發(fā)送請求也都有在ajax里面設置xhrFields:{withCredentials: true}屬性。

攔截器代碼

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zdyl.devicemanagement.common.exception.RRException;
import com.zdyl.devicemanagement.common.utils.AccountNumber;
import com.zdyl.devicemanagement.common.utils.RedisSavePrefix;
import com.zdyl.devicemanagement.common.utils.RedisUtils;
import com.zdyl.devicemanagement.common.utils.SystemConstants;
import com.zdyl.devicemanagement.entity.LcoUsers;
import com.zdyl.devicemanagement.entity.Login;
import com.zdyl.devicemanagement.service.LcoUsersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

@Slf4j
public class AccessInterceptor extends HandlerInterceptorAdapter {

  @Resource
  private RedisUtils redisUtils;
  @Resource
  private LcoUsersService lcoUsersService;

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    log.info("------------------------AccessInterceptor-------------------------");
    if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
      return super.preHandle(request, response, handler);
    }
    //獲取請求token,如果token不存在,直接返回401
    String token = getRequestToken(request);
    String loginId = getRequestloginId(request);
    if (StringUtils.isEmpty(token)) {
      throw new RRException("token為空", 401);
    }
    if (StringUtils.isEmpty(loginId)) {
      throw new RRException("loginId為空", 401);
    }
    Object users = redisUtils.getObject(redisUtils.getKey(RedisSavePrefix.Login, loginId), AccountNumber.loginDataBase);
    if (users == null) {
      throw new RRException("用戶尚未登錄", 401);
    }
    Login loginUser = JSONObject.parseObject(JSON.toJSONString(users), Login.class);
    if (!loginUser.getToken().equals(token)) {
      throw new RRException("token不匹配", 401);
    }
    Date loginTime = loginUser.getLoginTime();
    long exitTime = loginTime.getTime() / 1000 + 7200;
    long time = new Date().getTime();
    long nowTime = new Date().getTime() / 1000;
    if (nowTime > exitTime) {
      throw new RRException("token已過期!", 401);
    }
    QueryWrapper<LcoUsers> lcoUsersQueryWrapper = new QueryWrapper<>();
    lcoUsersQueryWrapper.eq("phone", loginUser.getLoginID());
    LcoUsers lcoUsers = lcoUsersService.getOne(lcoUsersQueryWrapper);
    request.setAttribute(SystemConstants.CURRENTUSER, lcoUsers);
    return super.preHandle(request, response, handler);
  }

  /**
   * 獲取請求的token
   */
  private String getRequestToken(HttpServletRequest httpRequest) {
    //從header中獲取token
    String host = httpRequest.getHeader("token");

    //如果header中不存在token,則從參數中獲取token
    if (StringUtils.isEmpty(host)) {
      host = httpRequest.getParameter("token");
    }
//    if (StringUtils.isEmpty(host)) {
//      Cookie[] cks = httpRequest.getCookies();
//      for (Cookie cookie : cks) {
//        if (cookie.getName().equals("yzjjwt")) {
//          host = cookie.getValue();
//          return host;
//        }
//      }
//    }
    return host;
  }

  /**
   * 獲取請求的loginId
   */
  private String getRequestloginId(HttpServletRequest httpRequest) {
    //從header中獲取token
    String loginId = httpRequest.getHeader("loginId");

    //如果header中不存在token,則從參數中獲取token
    if (StringUtils.isEmpty(loginId)) {
      loginId = httpRequest.getParameter("loginId");
    }
//    if (StringUtils.isEmpty(loginId)) {
//      Cookie[] cks = httpRequest.getCookies();
//      for (Cookie cookie : cks) {
//        if (cookie.getName().equals("yzjjwt")) {
//          loginId = cookie.getValue();
//          return loginId;
//        }
//      }
//    }
    return loginId;
  }

/**
 * 對跨域提供支持
 */
protected boolean addCors(ServletRequest request, ServletResponse response) throws Exception {
  HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  HttpServletResponse httpServletResponse = (HttpServletResponse) response;
  httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
  httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
  httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
  // 跨域時會首先發(fā)送一個option請求,這里我們給option請求直接返回正常狀態(tài)
  if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
    httpServletResponse.setStatus(HttpStatus.OK.value());
    return false;
  }
  return super.preHandle(request, response);
}


}

自定義異常RRException代碼

/**
 * 自定義異常
 */
public class RRException extends RuntimeException {
  private static final long serialVersionUID = 1L;

  private String message;
  private String code = "INVALID";
  private int status = 0;

  public RRException(String msg) {
    super(msg);
    this.message = msg;
  }

  public RRException(String msg, Throwable e) {
    super(msg, e);
    this.message = msg;
  }

  public RRException(String msg, String code) {
    super(msg);
    this.message = msg;
    this.code = code;
  }
  public RRException(String msg, int status) {
    super(msg);
    this.message = msg;
    this.status = status;
  }

  public RRException(String msg, String code, Throwable e) {
    super(msg, e);
    this.message = msg;
    this.code = code;
  }

  public String getMsg() {
    return message;
  }

  public void setMsg(String msg) {
    this.message = msg;
  }

  public String getCode() {
    return code;
  }

  public void setCode(String code) {
    this.code = code;
  }

  public int getStatus() {
    return status;
  }

  public void setStatus(int status) {
    this.status = status;
  }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • java實現單鏈表倒轉的方法

    java實現單鏈表倒轉的方法

    這篇文章主要為大家詳細介紹了java實現單鏈表倒轉的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 一文搞懂Mybatis-plus的分頁查詢操作

    一文搞懂Mybatis-plus的分頁查詢操作

    說起分頁機制,相信我們程序員都不陌生,今天,我就給大家分享一下Mybatis-plus的分頁機制,供大家學習和Copy,感興趣的可以了解一下
    2022-06-06
  • spring boot(四)之thymeleaf使用詳解

    spring boot(四)之thymeleaf使用詳解

    Thymeleaf 是一個跟 Velocity、FreeMarker 類似的模板引擎,它可以完全替代 JSP 。接下來通過本文給大家介紹spring boot(四)之thymeleaf使用詳解,需要的朋友可以參考下
    2017-05-05
  • 詳細總結Java堆棧內存、堆外內存、零拷貝淺析與代碼實現

    詳細總結Java堆棧內存、堆外內存、零拷貝淺析與代碼實現

    零拷貝,這是個耳熟能詳的名詞,是開發(fā)崗面試中經常提及的問題.最近在回顧Netty的基礎原理,還是把NIO中關于堆外內存的知識點過了一遍,這里就針對堆棧內存 堆外內存和零拷貝這幾個概念以及相關知識做一下記錄,需要的朋友可以參考下
    2021-05-05
  • java多線程編程之使用runnable接口創(chuàng)建線程

    java多線程編程之使用runnable接口創(chuàng)建線程

    實現Runnable接口的類必須使用Thread類的實例才能創(chuàng)建線程,通過Runnable接口創(chuàng)建線程分為以下兩步
    2014-01-01
  • 詳解重試框架Spring retry實踐

    詳解重試框架Spring retry實踐

    spring retry是從spring batch獨立出來的一個能功能,主要實現了重試和熔斷。這篇文章主要介紹了詳解重試框架Spring retry實踐,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 如何為?Spring?Boot?項目配置?Logback?日志

    如何為?Spring?Boot?項目配置?Logback?日志

    由于?Spring?Boot?的默認日志框架選用的?Logback,再加上?Log4j2?之前爆過嚴重的漏洞,所以我們這次就只關注?Logback,本文重點給大家介紹如何為?Spring?Boot?項目配置?Logback?日志,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • Java ArrayList.toArray(T[]) 方法的參數類型是 T 而不是 E的原因分析

    Java ArrayList.toArray(T[]) 方法的參數類型是 T 而不是 E的原因分析

    這篇文章主要介紹了Java ArrayList.toArray(T[]) 方法的參數類型是 T 而不是 E的原因分析的相關資料,需要的朋友可以參考下
    2016-04-04
  • 在spring中使用自定義注解注冊監(jiān)聽器的方法

    在spring中使用自定義注解注冊監(jiān)聽器的方法

    本篇文章主要介紹了在spring中使用自定義注解注冊監(jiān)聽器的方法,本文就是在分析監(jiān)聽器回調原理的基礎上,在spring環(huán)境中使用自定義的注解實現一個監(jiān)聽器。小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • Java Calendar日歷類的使用介紹

    Java Calendar日歷類的使用介紹

    Candendar類是一個抽象類,提供了一些獲取當前時間,或者指定的時間的字段和一些方法,我們可以通過一些方法與字段對他進行獲取當前天或者當月的一些信息
    2022-09-09

最新評論