检查用户是否登录,如果没有登录,跳转到指定页面
1、配置拦截
spring用xml配置文件+拦截器实现类的方式,而springboot用WebMvcConfigurer实现类+拦截器实现类的方式
这两个配置方式用一个就行了,但是拦截器实现类是通用的
1.1 xml配置文件的方式
- 编写xml配置文件
- 设置要拦截的路径
- 设置要放行的路径
- 设置拦截器的实现类
LoginInterceptor
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 设置当前拦截器要拦截的路径,/**拦截所有页面 -->
<mvc:mapping path="/**"/>
<!-- 设置不拦截的路径,不拦截这个访问地址 -->
<mvc:exclude-mapping path="/admin/to/login/page.html"/>
<mvc:exclude-mapping path="/admin/do/login.html"/>
<mvc:exclude-mapping path="/admin/logout.html"/>
<mvc:exclude-mapping path="/index.html"/>
<!-- 拦截器的bean -->
<bean class="com.wzw.crowd.funding.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
1.2 配置类的方式
- 先编写一个拦截器实现类
LoginInterceptor
- 在实现了
WebMvcConfigurer
的方法中添加拦截器
2、拦截器实现类
继承HandlerInterceptorAdapter
类
public class LoginInterceptor extends HandlerInterceptorAdapter {
/**
* 预处理回调方法,业务处理器处理请求之前被调用,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 通过request对象获取HttpSession对象
HttpSession session = request.getSession();
// 从Session域尝试获取已登录用户对象,用户是存在user中,这里取出来,判断是不是空的,如果是空的就没有登录
Admin admin = (Admin) session.getAttribute("user");
// 如果没有获取到Admin对象
if(admin == null) {
// 将提示消息存入request域,存入一个提示信息
request.setAttribute("message", "请先登录");
// 转发到登录页面
request.getRequestDispatcher("/WEB-INF/admin-login.jsp").forward(request, response);
return false;
}
// 如果admin对象有效,则放行继续执行后续操作
return true;
}
/**
* 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
/**
* 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
3、兼容ajax
上面的内容只能对普通的页面请求有效,对异步请求例如ajax是没有效果的,就算用户已经注销,但是依旧进行操作,页面是没有任何显示的,所以这里做一下兼容ajax
3.1 pom引入
这里需要转换JSON,导入JSON包,这里用的是google的
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
3.2 JSON响应格式的实体类
这里用了lombok,注释是lombok帮助生成了get和set方法,以及全参和无参构造函数,没有lombok就自己写get和set方法,以及全参和无参构造函数
/**
* ajax请求的响应格式
*
* @author Administrator
*
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ResultEntity<T> {
public static final String SUCCESS = "SUCCESS";
public static final String FAILED = "FAILED";
public static final String NO_MESSAGE = "NO_MESSAGE";
public static final String NO_DATA = "NO_DATA";
// 方便返回成功结果(不携带查询结果情况)
public static ResultEntity<String> successWithoutData() {
return new ResultEntity<String>(SUCCESS, NO_MESSAGE, NO_DATA);
}
// 方便返回成功结果(携带查询结果情况)
public static <E> ResultEntity<E> successWithData(E data) {
return new ResultEntity<E>(SUCCESS, NO_MESSAGE, data);
}
// 方便返回失败结果
public static <E> ResultEntity<E> failed(E data, String message) {
return new ResultEntity<E>(FAILED, message, data);
}
private String result;
private String message;
private T data;
}
3.3 判断是否异步请求工具类
/**
* 判断请求是否为异步请求
*
* @param request
* @return
*/
public boolean checkAsyncRequest(HttpServletRequest request) {
//获取相应请消息头
String accept = request.getHeader("Accept");
String xRequested = request.getHeader("X-Requested-With");
//判断请求消息头是否包含json的特征
if (stringEffective(accept) && accept.contains("application/json")
|| stringEffective(xRequested) && xRequested.contains("XMLHttpRequest")) {
return true;
}
return false;
}
/**
* 判断字符串是否有效
*
* @param source 待验证字符串
* @return true表示有效,false表示无效
*/
public boolean stringEffective(String source) {
return source != null && source.length() > 0;
}
3.4 改进后的登录拦截器
public class LoginInterceptor extends HandlerInterceptorAdapter {
/**
* 预处理回调方法,业务处理器处理请求之前被调用,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 通过request对象获取HttpSession对象
HttpSession session = request.getSession();
// 从Session域尝试获取已登录用户对象,用户是存在user中,这里取出来,判断是不是空的,如果是空的就没有登录
Admin admin = (Admin) session.getAttribute("user");
// 如果没有获取到Admin对象
if(admin == null) {
// 进一步判断当前请求是否是异步请求
boolean checkAsyncRequest = CrowdFundingUtils.checkAsyncRequest(request);
if (checkAsyncRequest) {
// 创建ResultEntity对象
ResultEntity<String> resultEntity = ResultEntity.failed(ResultEntity.NO_DATA,
"请登录后再操作!");
// ResultEntity对象转为JSON对象
Gson gson = new Gson();
String json = gson.toJson(resultEntity);
// 这只响应的内容类型
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(json);
return false;
}
// 将提示消息存入request域,存入一个提示信息
request.setAttribute("message", "请登录后再操作!");
// 转发到登录页面
request.getRequestDispatcher("/WEB-INF/admin-login.jsp").forward(request, response);
return false;
}
// 如果admin对象有效,则放行继续执行后续操作
return true;
}
/**
* 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
/**
* 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
这是用layer写的,就是这个样式,没有layer的话,可以直接alert查看报错信息,不做这个改进的话,页面没有任何反应
4、WebMvcConfigurer实现类
springboot就用这个实现类的方式实现,spring用xml方式就行,这个就不用了
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 配置跨域访问
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("*")
.maxAge(3600);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
/**
* 配置自定义拦截器
* addPathPatterns:相当于xml文件中的<mvc:mapping path="/**"/>
* excludePathPatterns:相当于xml文件中的<mvc:exclude-mapping path="/admin/to/login/page.html"/>,可以是数组
*/
registry.addInterceptor(new TraceAnnotationInterceptor()).addPathPatterns("/**")
.excludePathPatterns(trace_exclude_path);
}
}