springSecurity之如何添加自定義過(guò)濾器
springSecurity 添加自定義過(guò)濾器
我們知道,springSecurity其實(shí)就是將過(guò)濾器和aop進(jìn)行整合。其實(shí)我們也可以添加自己的過(guò)濾器。
很簡(jiǎn)單,配置如下
<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"/>
然后再來(lái)看看myFilter
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("進(jìn)來(lái)了我自定義的過(guò)濾器了"); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println("自定義過(guò)濾器鏈銷(xiāo)毀了"); } }
其實(shí)只要實(shí)現(xiàn)了javax.servlet.Filter就可以了,很low.
springSecurity 自定義認(rèn)證過(guò)濾器
繼承 Filter 基類(lèi) OncePerRequestFilter 保證每個(gè)請(qǐng)求轉(zhuǎn)發(fā)執(zhí)行一次
public class MyAuthenticationProcessingFilter extends OncePerRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter(requestWrapper, response); }
出現(xiàn)的問(wèn)題
在 filter 中消費(fèi)了 Request 中的 InputStream 導(dǎo)致后續(xù)的過(guò)濾器中無(wú)法調(diào)用 Request
解決方法
定義一個(gè) HttpServletRequestWrapper 類(lèi),將輸入流字節(jié)數(shù)據(jù)讀取出來(lái),以供使用,重新 getInputStream() 方法,將輸入流字節(jié)數(shù)組重新封裝成 ServletInputStream 輸入流即可,注意字符編碼
ServletRequestWrapper.java
public class ServletRequestWrapper extends HttpServletRequestWrapper { private byte[] body; private String requestParam; /** * Constructs a request object wrapping the given request. * @Description: 將 request 中的流信息讀取出來(lái)供外部使用,將流緩存起來(lái),傳到下一個(gè) 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
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(); } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
非常詳細(xì)的Java異常處理機(jī)制知識(shí)整理大全
Java異常指在程序運(yùn)行時(shí)可能出現(xiàn)的一些錯(cuò)誤,比如試圖打開(kāi)一個(gè)根本不存在的文件等,異常處理將會(huì)改變程序的控制流程,讓程序有機(jī)會(huì)對(duì)錯(cuò)誤做出處理,下面這篇文章主要給大家介紹了關(guān)于Java異常處理機(jī)制知識(shí)整理的相關(guān)資料,需要的朋友可以參考下2022-11-11java中生成任意之間數(shù)的隨機(jī)數(shù)詳解
這篇文章主要介紹了java中生成任意之間數(shù)的隨機(jī)數(shù)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09SpringBoot處理JSON數(shù)據(jù)方法詳解
這篇文章主要介紹了SpringBoot整合Web開(kāi)發(fā)中Json數(shù)據(jù)處理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-10-10Java?zxing實(shí)現(xiàn)生成并解析二維碼與條形碼
這篇文章主要為大家詳細(xì)介紹了Java如何通過(guò)zxing實(shí)現(xiàn)生成并解析二維碼與條形碼,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-11-11SpringBoot中將@Bean方法解析為BeanDefinition詳解
這篇文章主要介紹了SpringBoot中將@Bean方法解析為BeanDefinition詳解,得到的BeanDefinition是ConfigurationClassBeanDefinition類(lèi)型,會(huì)為BeanDefinition設(shè)置factoryMethodName,這意味著當(dāng)實(shí)例化這個(gè)bean的時(shí)候?qū)⒉捎霉S方法,需要的朋友可以參考下2023-12-12一文帶你學(xué)會(huì)Spring?JDBC的使用
JDBC?就是?數(shù)據(jù)庫(kù)開(kāi)發(fā)?操作的?代名詞,因?yàn)橹灰乾F(xiàn)代商業(yè)項(xiàng)目的開(kāi)發(fā)那么一定是離不開(kāi)?數(shù)據(jù)庫(kù)?的,不管你搞的是什么,只要是想使用動(dòng)態(tài)的開(kāi)發(fā)結(jié)構(gòu),那么一定就是?JDBC?,那么下面來(lái)教教大家傳統(tǒng)JDBC的使用2022-09-09java后端操作樹(shù)結(jié)構(gòu)的案例代碼
這篇文章主要介紹了java后端操作樹(shù)結(jié)構(gòu),樹(shù)結(jié)構(gòu)的三種組裝方式(遞歸.雙層for循環(huán),map),通過(guò)實(shí)例代碼介紹了使用遞歸查詢(xún)某個(gè)節(jié)點(diǎn)所在的樹(shù)結(jié)構(gòu),需要的朋友可以參考下2023-10-10Java中消息隊(duì)列任務(wù)的平滑關(guān)閉詳解
對(duì)于消息隊(duì)列的監(jiān)聽(tīng),我們一般使用Java寫(xiě)一個(gè)獨(dú)立的程序,在Linux服務(wù)器上運(yùn)行。程序啟動(dòng)后,通過(guò)消息隊(duì)列客戶(hù)端接收消息,放入一個(gè)線(xiàn)程池進(jìn)行異步處理,并發(fā)的快速處理。這篇文章主要給大家介紹了關(guān)于Java中消息隊(duì)列任務(wù)的平滑關(guān)閉的相關(guān)資料,需要的朋友可以參考下。2017-11-11Jenkins發(fā)送測(cè)試報(bào)告郵件過(guò)程詳解
這篇文章主要介紹了Jenkins發(fā)送測(cè)試報(bào)告郵件過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07