欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Springboot前后端分離項(xiàng)目配置跨域?qū)崿F(xiàn)過(guò)程解析

 更新時(shí)間:2020年08月07日 10:31:47   作者:william_zhao  
這篇文章主要介紹了Springboot前后端分離項(xiàng)目配置跨域?qū)崿F(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

項(xiàng)目登錄流程如下

用戶進(jìn)入前端登錄界面,輸入賬號(hào)密碼等,輸入完成之后前端發(fā)送請(qǐng)求到后端(攔截器不會(huì)攔截登錄請(qǐng)求),后端驗(yàn)證賬號(hào)密碼等成功之后生成Token并存儲(chǔ)到數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)中包含該Token過(guò)期時(shí)間,然后返回生成的Token到前端。

前端收到Token,表示登錄成功,把這個(gè)Token存儲(chǔ)本地。然后跳轉(zhuǎn)到用戶中心頁(yè)面,用戶中心頁(yè)面在ajax的請(qǐng)求頭中帶上Token,跟隨請(qǐng)求用戶數(shù)據(jù)接口一起帶到后端。

后端通過(guò)攔截器攔截到這個(gè)請(qǐng)求,去判斷這個(gè)Token是否有效,有效就放過(guò)去做他該做的事情,無(wú)效就拋出異常。

跨域配置

先說(shuō)一下這個(gè)前后分離的項(xiàng)目,已經(jīng)配置過(guò)跨域這些問(wèn)題。我這里后端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ā)送請(qǐng)求也都有在ajax里面設(shè)置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);
    }
    //獲取請(qǐng)求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已過(guò)期!", 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);
  }

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

    //如果header中不存在token,則從參數(shù)中獲取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;
  }

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

    //如果header中不存在token,則從參數(shù)中獲取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;
  }

/**
 * 對(duì)跨域提供支持
 */
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"));
  // 跨域時(shí)會(huì)首先發(fā)送一個(gè)option請(qǐng)求,這里我們給option請(qǐng)求直接返回正常狀態(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;
  }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java實(shí)現(xiàn)單鏈表倒轉(zhuǎn)的方法

    java實(shí)現(xiàn)單鏈表倒轉(zhuǎn)的方法

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

    一文搞懂Mybatis-plus的分頁(yè)查詢操作

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

    spring boot(四)之thymeleaf使用詳解

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

    詳細(xì)總結(jié)Java堆棧內(nèi)存、堆外內(nèi)存、零拷貝淺析與代碼實(shí)現(xiàn)

    零拷貝,這是個(gè)耳熟能詳?shù)拿~,是開(kāi)發(fā)崗面試中經(jīng)常提及的問(wèn)題.最近在回顧Netty的基礎(chǔ)原理,還是把NIO中關(guān)于堆外內(nèi)存的知識(shí)點(diǎn)過(guò)了一遍,這里就針對(duì)堆棧內(nèi)存 堆外內(nèi)存和零拷貝這幾個(gè)概念以及相關(guān)知識(shí)做一下記錄,需要的朋友可以參考下
    2021-05-05
  • java多線程編程之使用runnable接口創(chuàng)建線程

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

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

    詳解重試框架Spring retry實(shí)踐

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

    如何為?Spring?Boot?項(xiàng)目配置?Logback?日志

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

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

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

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

    本篇文章主要介紹了在spring中使用自定義注解注冊(cè)監(jiān)聽(tīng)器的方法,本文就是在分析監(jiān)聽(tīng)器回調(diào)原理的基礎(chǔ)上,在spring環(huán)境中使用自定義的注解實(shí)現(xiàn)一個(gè)監(jiān)聽(tīng)器。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • Java Calendar日歷類的使用介紹

    Java Calendar日歷類的使用介紹

    Candendar類是一個(gè)抽象類,提供了一些獲取當(dāng)前時(shí)間,或者指定的時(shí)間的字段和一些方法,我們可以通過(guò)一些方法與字段對(duì)他進(jìn)行獲取當(dāng)前天或者當(dāng)月的一些信息
    2022-09-09

最新評(píng)論