您好,登录后才能下订单哦!
小编给大家分享一下Springboot如何实现前后端分离项目配置跨域,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!
项目登录流程如下
用户进入前端登录界面,输入账号密码等,输入完成之后前端发送请求到后端(拦截器不会拦截登录请求),后端验证账号密码等成功之后生成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);
  }
}前端每次发送请求也都有在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")); // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态 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;
  }
}看完了这篇文章,相信你对Springboot如何实现前后端分离项目配置跨域有了一定的了解,想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。