springSecurity 添加自定义过滤器
我们知道,springSecurity其实就是将过滤器和aop进行整合。其实我们也可以添加自己的过滤器。
很简单,配置如下
1
2
3
4
5
6
7
8
|
< http use-expressions = "false" entry-point-ref = "loginEntryPoint" > < intercept-url pattern = "/user.jsp" access = "ROLE_USER,ROLE_ADMIN" /> < intercept-url pattern = "/admin.jsp" access = "ROLE_ADMIN" /> < intercept-url pattern = "/**" access = "IS_AUTHENTICATED_FULLY" /> < form-login /> < custom-filter ref = "myFilter" position = "LAST" /> </ http > < beans:bean id = "myFilter" class = "com.ezhiyang.springSecurity.MyFilter" /> |
然后再来看看myFilter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class MyFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println( "进来了我自定义的过滤器了" ); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println( "自定义过滤器链销毁了" ); } } |
其实只要实现了javax.servlet.Filter就可以了,很low.
springSecurity 自定义认证过滤器
继承 Filter 基类 OncePerRequestFilter 保证每个请求转发执行一次
1
2
3
4
5
|
public class MyAuthenticationProcessingFilter extends OncePerRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter(requestWrapper, response); } |
出现的问题
在 filter 中消费了 Request 中的 InputStream 导致后续的过滤器中无法调用 Request
解决方法
定义一个 HttpServletRequestWrapper 类,将输入流字节数据读取出来,以供使用,重新 getInputStream() 方法,将输入流字节数组重新封装成 ServletInputStream 输入流即可,注意字符编码
ServletRequestWrapper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
public class ServletRequestWrapper extends HttpServletRequestWrapper { private byte [] body; private String requestParam; /** * Constructs a request object wrapping the given request. * @Description: 将 request 中的流信息读取出来供外部使用,将流缓存起来,传到下一个 filter 中 * @param request The request to wrap * @throws IllegalArgumentException if the request is null */ public ServletRequestWrapper(HttpServletRequest request) { super (request); requestParam = HttpUtil.getBodyString(request); body = requestParam.getBytes(Charset.forName( "utf-8" )); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader( new InputStreamReader(getRequest().getInputStream(), Charset.forName( "UTF-8" ))); } @Override public ServletInputStream getInputStream() throws IOException { return new CustomServletInputStream(); } private class CustomServletInputStream extends ServletInputStream { private ByteArrayInputStream inputStream = new ByteArrayInputStream(body); @Override public boolean isFinished() { return false ; } @Override public boolean isReady() { return false ; } @Override public void setReadListener(ReadListener listener) { } @Override public int read() throws IOException { return inputStream.read(); } } public String getRequestParam() { return requestParam; } } |
HttpUtil.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public class HttpUtil { public static String getBodyString(ServletRequest request) { BufferedReader bufferedReader = null ; InputStream inputStream = null ; StringBuilder sb = new StringBuilder( "" ); try { inputStream = request.getInputStream(); bufferedReader = new BufferedReader( new InputStreamReader(inputStream, Charset.forName( "utf-8" ))); String line = "" ; while ((line = bufferedReader.readLine()) != null ) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedReader != null ) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null ) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } } |
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/weixin_41751625/article/details/79846581