微前端架构如何改变企业的开发模式与效率提升
749
2023-05-03
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
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
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.addxwdnorAllowedHeader("*");
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
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;
}
}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~