Spring Security之默認(rèn)的過濾器鏈及自定義Filter操作
過濾器順序從上到下
自定義 Filter自定義的 Filter 建議繼承 GenericFilterBean,本文示例:
package com.example.filter;import org.springframework.web.filter.GenericFilterBean;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;/** * @author 咸魚 * @date 2019-05-26 18:02 */public class BeforeLoginFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println('在 UsernamePasswordAuthenticationFilter 前調(diào)用');chain.doFilter(request, response); }}配置自定義 Filter 在 Spring Security 過濾器鏈中的位置
配置很簡單,本文示例:
@Override protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers('/').permitAll().antMatchers('/user/**').hasAuthority('USER').and().formLogin().loginPage('/login').defaultSuccessUrl('/user').and().logout().logoutUrl('/logout').logoutSuccessUrl('/login');// 在 UsernamePasswordAuthenticationFilter 前添加 BeforeLoginFilterhttp.addFilterBefore(new BeforeLoginFilter(), UsernamePasswordAuthenticationFilter.class);// 在 CsrfFilter 后添加 AfterCsrfFilterhttp.addFilterAfter(new AfterCsrfFilter(), CsrfFilter.class); }
說明:
HttpSecurity 有三個(gè)常用方法來配置:
addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter)
在 beforeFilter 之前添加 filter
addFilterAfter(Filter filter, Class<? extends Filter> afterFilter)
在 afterFilter 之后添加 filter
addFilterAt(Filter filter, Class<? extends Filter> atFilter)
在 atFilter 相同位置添加 filter, 此 filter 不覆蓋 filter
通過在不同 Filter 的 doFilter() 方法中加斷點(diǎn)調(diào)試,可以判斷哪個(gè) filter 先執(zhí)行,從而判斷 filter 的執(zhí)行順序 。
spring security添加自定義過濾器1、定義自己的過濾器
2、指定位置,通過HttpSecurity的方法指定
定義過濾器package com.qiudaozhang.springsecurity.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class RequestHeadCheckFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {var httpRequest = (HttpServletRequest) servletRequest;var httpResponse = (HttpServletResponse) servletResponse;String requestId = httpRequest.getHeader('Request-id');if(requestId == null || requestId.isBlank()) { httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST); return;}filterChain.doFilter(servletRequest,servletResponse); }}
package com.qiudaozhang.springsecurity.filter;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class RequestParamCheckFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {var httpRequest = (HttpServletRequest) servletRequest;var httpResponse = (HttpServletResponse) servletResponse;String timestamp = httpRequest.getParameter('timestamp');if(timestamp == null || timestamp.isBlank()) { httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); return;}filterChain.doFilter(servletRequest,servletResponse); }}指定位置
HttpSecurity中有兩個(gè)方法,指定過濾器的位置,一個(gè)指定在誰前面,一個(gè)指定在誰后面。
public HttpSecurity addFilterAfter(Filter filter, Class<? extends Filter> afterFilter) { this.comparator.registerAfter(filter.getClass(), afterFilter); return this.addFilter(filter); } public HttpSecurity addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter) { this.comparator.registerBefore(filter.getClass(), beforeFilter); return this.addFilter(filter); }
package com.qiudaozhang.springsecurity.config;import com.qiudaozhang.springsecurity.filter.RequestHeadCheckFilter;import com.qiudaozhang.springsecurity.filter.RequestParamCheckFilter;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;@Configurationpublic class ProjectConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception {http.addFilterBefore(new RequestHeadCheckFilter(),BasicAuthenticationFilter.class).addFilterAfter(new RequestParamCheckFilter(),BasicAuthenticationFilter.class).authorizeRequests().anyRequest().permitAll(); }}測(cè)試
準(zhǔn)備一個(gè)端點(diǎn)測(cè)試
package com.qiudaozhang.springsecurity.controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloController { @GetMapping('hello') public String hello () {return 'hello'; }}
當(dāng)前沒有傳遞timestamp參數(shù),所以參照約定,過濾器直接給出403.
當(dāng)前頭部信息和參數(shù)信息都提供了,檢測(cè)通過。
實(shí)際應(yīng)用場(chǎng)景 檢測(cè)相關(guān)的頭部,參數(shù)等等信息日志過濾器,將所有請(qǐng)求的相關(guān)數(shù)據(jù)記錄下來特殊的權(quán)限校驗(yàn)等等。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. moment轉(zhuǎn)化時(shí)間戳出現(xiàn)Invalid Date的問題及解決2. python爬蟲實(shí)戰(zhàn)之制作屬于自己的一個(gè)IP代理模塊3. ajax請(qǐng)求后臺(tái)得到j(luò)son數(shù)據(jù)后動(dòng)態(tài)生成樹形下拉框的方法4. Ajax返回值類型與用法實(shí)例分析5. 解決ajax請(qǐng)求后臺(tái),有時(shí)收不到返回值的問題6. HTML 絕對(duì)路徑與相對(duì)路徑概念詳細(xì)7. asp批量添加修改刪除操作示例代碼8. 如何在jsp界面中插入圖片9. .NET6打包部署到Windows Service的全過程10. 詳解盒子端CSS動(dòng)畫性能提升
