今天想要手动的实现以下Filter权限控制,但是发现使用springboot的filter和之前的不一样,之前使用Servlet3.0只需要使用@WebFilter注解或者在web.xml文件中配置以下即可。但是springboot中没有web.xml文件,于是我很自然的使用注解,然后发现怎么也配置不上去,那么怎么办呢,没错,查文档。
经过一番查阅,原来spring中提供了三个注册器:FilterRegistrationBean、ServletRegistrationBean、ListenerRegistrationBean,分别用来配置Filter、Servlet和Listener,那么知道怎么回事了,下面先写一个Filter
package xin.sun.filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* Created by sun on 2017/8/4.
*/
public class LoginFilter extends HttpFilter{
/**
* ajax请求头key
*/
public static final String AJAX_HEAD_KEY = "x-requested-with";
/**
* ajax请求头值
*/
public static final String AJAX_HEAD_VALUES = "XMLHttpRequest";
private String uncheckedUrl;
private String sessionKey;
@Override
public void doFilter(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpSession session = servletRequest.getSession();
List<String> urls = Arrays.asList(uncheckedUrl.split(","));
String servletPath = servletRequest.getServletPath();
//不需要过滤的URL直接放行
if(urls.contains(servletPath)){
filterChain.doFilter(servletRequest, servletResponse);
return;
}
String username = (String) session.getAttribute(sessionKey);
if (username == null || "".equals(username)) {
//判断Ajax请求
String reqMethod = servletRequest.getHeader(AJAX_HEAD_KEY);
if (AJAX_HEAD_VALUES.equalsIgnoreCase(reqMethod)) {
servletResponse.setHeader("sessionstatus","timeout");
servletResponse.sendError(518, "session timeout.");
filterChain.doFilter(servletRequest, servletResponse);
return ;
}
//非ajax请求
servletResponse.setHeader("Cache-Control", "no-store");
servletResponse.setDateHeader("Expires", 0);
servletResponse.setHeader("Prama", "no-cache");
//获取绝对路劲的根路径
String basePath = servletRequest.getScheme()+"://"+servletRequest.getServerName()+":"+
servletRequest.getServerPort()+servletRequest.getContextPath();
//重定向到登录页面
servletResponse.sendRedirect(basePath+"/login");
return;
}
filterChain.doFilter(servletRequest,servletResponse);
}
/**
* 初始化,获取初始化参数
*/
public void init(){
uncheckedUrl = getFilterConfig().getInitParameter("uncheckedUrl");
sessionKey = getFilterConfig().getInitParameter("sessionKey");
}
}
其实很多人在拦截的时候没有拦截ajax请求,那么会导致一个什么问题呢?当你的session超时后,你在页面中还可以发送ajax请求,是不是很荒唐,没错filter拦截ajax请求是需要做判断的,上面也给出了代码。
这个HttpFilter是我仿照HttpServlet写的,还是很实用的,我也贴出来一份
package xin.sun.filter;
import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by sun on 2017/8/4.
* 仿照HttpServlert,自定义HttpFilter,简化开发,
*/
public abstract class HttpFilter implements Filter {
private FilterConfig filterConfig;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.init();
}
/**
* 获取过滤器配置对象
* @return
*/
public FilterConfig getFilterConfig(){
return this.filterConfig;
}
/**
* 获取初始化参数
* @param key
* @return
*/
public String getInitParameter(String key){
return getFilterConfig().getInitParameter(key);
}
/**
* 获取应用上下文
* @return
*/
public ServletContext getServletContext() {
return this.getFilterConfig().getServletContext();
}
/**
* 提供用户初始化方法
* @throws ServletException
*/
public void init() throws ServletException {
}
/**
* 重写doFilter(),把Servlert***转换为HttpServlert***
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest)servletRequest;
response = (HttpServletResponse)servletResponse;
} catch (ClassCastException var6) {
throw new ServletException("non-HTTP request or response");
}
this.doFilter(request,response,filterChain);
}
/**
* 提供一个doFilter()方法,用户必须实现
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
public abstract void doFilter(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException ;
@Override
public void destroy() {
}
}
好了,重头戏来了,在springboot中配置这个filter
package xin.sun.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by sun on 2017/8/4.
* 该类用于注册Filter
*/
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean loginFilterRegistration(){
FilterRegistrationBean registration = new FilterRegistrationBean();
//注入过滤器
registration.setFilter(new LoginFilter());
//拦截规则
registration.addUrlPatterns("/*");
//初始化参数
registration.addInitParameter("uncheckedUrl","/login,/registry,/loginServlet");
registration.addInitParameter("sessionKey","SESSIONKEY");
//过滤器名称
registration.setName("loginFilter");
//是否自动注册 ,false 取消Filter的自动注册
registration.setEnabled(true);
//过滤器顺序
registration.setOrder(10);
return registration;
}
}
那么Servlet其实原理是一样的,只是配置上略有不同罢了,自己去体会一下,这里就只给出代码了
package xin.sun.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by sun on 2017/8/4.
*/
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取绝对路劲的根路径
String basePath = req.getScheme()+"://"+req.getServerName()+":"+
req.getServerPort()+req.getContextPath();
String username = req.getParameter("username");
String password = req.getParameter("password");
if(username.equals("admin")&&password.equals("123456")){
req.getSession().setAttribute("SESSIONKEY",username);
resp.sendRedirect(basePath + "/indexPage");
}else {
resp.sendRedirect(basePath + "/login");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
package xin.sun.servlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by sun on 2017/8/4.
*/
@Configuration
public class ServletConfig {
@Bean
public ServletRegistrationBean loginServletRegistration(){
ServletRegistrationBean registration = new ServletRegistrationBean();
//设置servlet
registration.setServlet(new LoginServlet());
//是否自动注册 ,false 取消Filter的自动注册
registration.setEnabled(true);
//设置URL映射地址
List urlMapping = new ArrayList<String>();
urlMapping.add("/loginServlet");
registration.setUrlMappings(urlMapping);
//设置加载就启动
registration.setLoadOnStartup(1);
//设置初始化参数
Map initParams = new HashMap<String, String>();
initParams.put("key1","value1");
registration.setInitParameters(initParams);
return registration;
}
}
那么Listener也是一样的操作,照葫芦画瓢,留给大家去试试吧