一、spring boot 后台
- 拦截器
spring boot 推荐使用拦截器(拦截器是记忆web框架,过滤器是基于servlet 容器)
实现HandlerInterceptor接口,处理拦截器的相应操作
import com.gsww.human.entity.HumanUser;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @author: TuoPeng
* @Date: 2020/3/12 Time: 10:46
* 拦截器
*/
public class AccessInterceptor implements HandlerInterceptor {
/**
* 在请求处理之前进行调用(controller方法调用之前)
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
HumanUser humanUser = (HumanUser)session.getAttribute("humanUser");
if (humanUser == null){
response.setStatus(401);
}
return true;
}
/**
* 在请求处理之后进行调用,但是在试图渲染之前(Controller方法调用之后)
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 在整个请求结束之后被调用,也就是DispatcherServlet 渲染了对应视图之后执行(主要是用于资源的清理工作)
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
在拦截器中配置需要拦截的接口地址(如需要登录之后才能调用的接口)接口地址拦截和不需要拦截的接口(如验证码接口)
@Override
public void addInterceptors(InterceptorRegistry registry){
InterceptorRegistration registration = registry.addInterceptor(new AccessInterceptor());
registration.addPathPatterns("/**");
registration.excludePathPatterns("/kaptcha/defaultKaptcha","/yhjk/humanUser/login");
}
- 遇到问题
1)登录问题:
问题描述:登录过期后(sesssion过期),前端调用接口是请求返回failed,session与前一次请求的session不一致(ps:判断依据为两次的sessionId不一致)。
问题成因:由于前端使用了vue(iview框架),所以会遇到跨域的问题,起初使用的是注解的方式进行跨域处理,但是同时也会遇到一个问题,那就是当调用的接口被拦截时,无法调用的接口从而导致跨域失败,http请求返回failed,前台无法判读接口是因为接口逻辑原因出现问题,还是因为根本无法调用到接口出现问题。
解决方案:重新配置全局的跨域,不只是在调用接口时进行跨域
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.WebMvcConfigurer;
/**
* @author: TuoPeng
* @Date: 2020/3/12 Time: 11:01
*/
@Configuration
public class LoginConfig implements WebMvcConfigurer {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 设置允许跨域请求的域名
config.addAllowedOrigin("*");
// 是否允许证书 不再默认开启
// config.setAllowCredentials(true);
// 设置允许的方法
config.addAllowedMethod("*");
// 允许任何头
config.addAllowedHeader("*");
config.addExposedHeader("token");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
}
问题二、浏览器cookie的丢失问题
问题描述:用于谷歌浏览器的问题导致用户登录时,cookie的丢失。在配置登录拦截,使用户登录停留在登录页面
A cookie associated with a cross-site resource at http://127.0.0.1/ was set without the `SameSite` attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/563352162218803
解决方案:前往chrome://flags/ 设置SameSite by default cookies和Cookies without SameSite must be secure为disabled
详细解决办法见:SameSite Cookie 变更:您需要了解的都在这里
二、 vue
对于登录页面的html代码不在赘述,百度的页面应该有很多
路由拦截
请求拦截
axios.interceptors.request.use(
config => {
let token = getStore('token')
if (token && config.url.indexOf('oauth') < 0) {
config.headers.Authorization = token;
}
if (config.url.indexOf('oauth') > 0) {
// 登陆认证 格式为表单形式提交
config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
}
return config;
},
err => {
return Promise.reject(err);
}
);
响应拦截
axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
debugger
// 401 清除token信息并跳转到登录页面
// Message.error('登录超时,请重新登录');
// debugger
store.commit('logout');
// 只有在当前路由不是登录页面才跳转
router.currentRoute.path !== "/" &&
router.replace({
path: "/",
query: {
redirect: router.currentRoute.path
}
});
}
}
return Promise.reject(error.response.data);
}
);