最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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微信企業(yè)號(hào)開(kāi)發(fā)之發(fā)送消息(文本、圖片、語(yǔ)音)

    java微信企業(yè)號(hào)開(kāi)發(fā)之發(fā)送消息(文本、圖片、語(yǔ)音)

    這篇文章主要為大家詳細(xì)介紹了java微信企業(yè)號(hào)開(kāi)發(fā)之發(fā)送消息,發(fā)送類(lèi)型包括文本、圖片、語(yǔ)音,感興趣的小伙伴們可以參考一下
    2016-06-06
  • SpringBoot中Token登錄授權(quán)、續(xù)期和主動(dòng)終止的方案流程分析

    SpringBoot中Token登錄授權(quán)、續(xù)期和主動(dòng)終止的方案流程分析

    SpringBoot項(xiàng)目中,基于Token的登錄授權(quán)方案主要有兩種:利用Session/Cookie和JWT,Cookie/Session方案有狀態(tài),不適合分布式架構(gòu),而JWT雖無(wú)狀態(tài),但存在過(guò)期時(shí)間不可強(qiáng)制失效、一次性等缺點(diǎn),本文介紹SpringBoot中Token登錄授權(quán)、續(xù)期和主動(dòng)終止的方案,感興趣的朋友一起看看吧
    2024-09-09
  • 在SSM中配置了事務(wù)控制但沒(méi)生效的問(wèn)題

    在SSM中配置了事務(wù)控制但沒(méi)生效的問(wèn)題

    這篇文章主要介紹了在SSM中配置了事務(wù)控制但沒(méi)生效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • SpringBoot?MDC全局鏈路最新完美解決方案

    SpringBoot?MDC全局鏈路最新完美解決方案

    MDC 在 Spring Boot 中的作用是為日志事件提供上下文信息,并將其與特定的請(qǐng)求、線程或操作關(guān)聯(lián)起來(lái),通過(guò)使用 MDC,可以更好地理解和分析日志,并在多線程環(huán)境中確保日志的準(zhǔn)確性和一致性,這篇文章主要介紹了SpringBoot?MDC全局鏈路解決方案,需要的朋友可以參考下
    2023-08-08
  • Java如何設(shè)置PDF文檔背景色詳解

    Java如何設(shè)置PDF文檔背景色詳解

    這篇文章主要介紹了Java如何設(shè)置PDF文檔背景色詳解,一般生成的PDF文檔默認(rèn)的文檔底色為白色,我們可以通過(guò)一定方法來(lái)更改文檔的背景色,以達(dá)到文檔美化以及保護(hù)雙眼的作用。 以下內(nèi)容提供了Java編程來(lái)設(shè)置PDF背景色的方法,需要的朋友可以參考下
    2019-07-07
  • Java實(shí)現(xiàn)三子棋游戲

    Java實(shí)現(xiàn)三子棋游戲

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 如何通過(guò)Maven倉(cāng)庫(kù)安裝Spire系列的Java產(chǎn)品

    如何通過(guò)Maven倉(cāng)庫(kù)安裝Spire系列的Java產(chǎn)品

    這篇文章主要介紹了如何通過(guò)Maven倉(cāng)庫(kù)安裝Spire系列的Java產(chǎn)品,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • SpringBoot3如何集成Hazelcast

    SpringBoot3如何集成Hazelcast

    Hazelcast是一款優(yōu)秀的開(kāi)源內(nèi)存數(shù)據(jù)網(wǎng)格平臺(tái),它能夠提供分布式數(shù)據(jù)存儲(chǔ)和緩存解決方案,通過(guò)與SpringBoot3的整合,開(kāi)發(fā)者可以輕松實(shí)現(xiàn)分布式緩存、數(shù)據(jù)共享和會(huì)話管理等功能,Hazelcast的內(nèi)存數(shù)據(jù)網(wǎng)格特性支持高性能的緩存系統(tǒng),能夠減少數(shù)據(jù)庫(kù)訪問(wèn)次數(shù),提升應(yīng)用性能
    2024-10-10
  • Java實(shí)現(xiàn)文件壓縮為zip和解壓zip壓縮包

    Java實(shí)現(xiàn)文件壓縮為zip和解壓zip壓縮包

    這篇文章主要為大家介紹了Java如何實(shí)現(xiàn)將文件壓縮為zip以及解壓zip壓縮包,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以動(dòng)手嘗試一下
    2022-06-06
  • Java常用的數(shù)據(jù)脫敏方法(手機(jī)、郵箱、身份證號(hào))

    Java常用的數(shù)據(jù)脫敏方法(手機(jī)、郵箱、身份證號(hào))

    這篇文章主要給大家介紹了關(guān)于Java常用的數(shù)據(jù)脫敏(手機(jī)、郵箱、身份證號(hào))的相關(guān)資料,信息脫敏對(duì)某些敏感信息通過(guò)脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù),需要的朋友可以參考下
    2023-07-07

最新評(píng)論

松原市| 宜兴市| 黄浦区| 青田县| 东方市| 瑞昌市| 吉安市| 鹤山市| 邹平县| 安泽县| 克东县| 甘洛县| 旺苍县| 红桥区| 徐汇区| 永康市| 鹤峰县| 旬邑县| 许昌市| 惠来县| 南涧| 黑龙江省| 台山市| 长岛县| 西丰县| 睢宁县| 皮山县| 乌鲁木齐县| 集贤县| 湾仔区| 崇阳县| 枝江市| 蓬莱市| 宣武区| 临猗县| 正定县| 白沙| 张掖市| 永仁县| 新干县| 佛坪县|