1. 程式人生 > >spring boot-使用Filter實現Header認證

spring boot-使用Filter實現Header認證

前言

假設客戶端在http請求中,已經加入了Header的認證資訊,例如:

HttpPost post = new HttpPost("http://localhost:8990/sendMail");
				StringEntity entity = new StringEntity(json, "utf-8");
				entity.setContentType("application/json");
				post.setEntity(entity);
				// 設定驗證頭資訊
				post.addHeader("token", "WEFGYHJIKLTY4RE6DF29HNBCFD13ER87");
那麼服務端怎麼通過Filter,來驗證客戶端的token是否有效了?請接著往下看。

一、實現自定義Filter

1、實現Filter介面

我們要自定義Filter,只需實現Filter介面即可

2、覆寫doFilter方法

根據業務邏輯,來覆寫doFilter方法

示例如下:

@Slf4j
@Component
@WebFilter(urlPatterns={"/sendMail/*"}, filterName="tokenAuthorFilter")
public class TokenAuthorFilter implements Filter {

	@Autowired
	private AuthorizationRepository repository;

	@Override
	public void destroy() {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest)request;
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json; charset=utf-8");
		String token = req.getHeader("token");
		Response res = new Response();
		boolean isFilter = false;
		if (null == token || token.isEmpty()) {
			res.setSuccess(false);
			res.setErrorCode("403");
			res.setErrorMessage("token沒有認證通過!原因為:客戶端請求引數中無token資訊");
		} else {
			Authorization auth = repository.findByToken(token);
			if (null == auth) {
				res.setSuccess(false);
				res.setErrorCode("403");
				res.setErrorMessage("token沒有認證通過!原因為:客戶端請求中認證的token資訊無效,請檢視申請流程中的正確token資訊");
			}else if((auth.getStatus() == 0)){
				res.setSuccess(false);
				res.setErrorCode("401");
				res.setErrorMessage("該token目前已處於停用狀態,請聯絡郵件系統管理員確認!");
			}else{
				isFilter = true;
				res.setSuccess(true);
			}
		}
		if(!res.isSuccess()){
			PrintWriter writer = null;
			OutputStreamWriter osw = null;
			try {
				osw = new OutputStreamWriter(response.getOutputStream() , "UTF-8");
				writer = new PrintWriter(osw, true);
				String jsonStr = ObjectMapperInstance.getInstance().writeValueAsString(res);
				writer.write(jsonStr);
				writer.flush();
				writer.close();
				osw.close();
			} catch (UnsupportedEncodingException e) {
				log.error("過濾器返回資訊失敗:" + e.getMessage(), e);
			} catch (IOException e) {
				log.error("過濾器返回資訊失敗:" + e.getMessage(), e);
			} finally {
				if (null != writer) {
					writer.close();
				}
				if(null != osw){
					osw.close();
				}
			}
			return;
		}
		if(isFilter){
			log.info("token filter過濾ok!");
			chain.doFilter(request, response);
		}
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

}

通過上面的幾步,就實現了一個自定義的Filter。

3、註冊Filter

接下來,需要註冊這個過濾器,spring boot提供了以下兩種註冊方式。

3.1 是用註解註冊

在Filter上新增如下註解即可

@Slf4j

@Component
@WebFilter(urlPatterns={"/sendMail/*"}, filterName="tokenAuthorFilter")
public class TokenAuthorFilter implements Filter {

@WebFilter註解的作用就是用來註冊Filter,通過這種方式註冊的Filter,需要在啟動類上加上@ServletComponentScan註解才能生效,如下:

@ServletComponentScan
public class MailserviceApplication {

	public static void main(String[] args) {
		SpringApplication.run(MailserviceApplication.class, args);
	}
}

3.2 手動配置Filter

@Configuration
@Component
public class FilterConfig {
	
	@Autowired
	private TokenAuthorFilter filter;
	
	@Bean
    public FilterRegistrationBean  filterRegistrationBean() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(filter);
        List<String> urlPatterns = new ArrayList<String>();
        urlPatterns.add("/sendMail/*");// 設定匹配的url
        registrationBean.setUrlPatterns(urlPatterns);
        return registrationBean;
    }
}

上面兩種方式雖然使用上有些不一樣,但是本質都是一樣的,都會呼叫FilterRegistrationBean來進行註冊。

二、spring boot內建的Filter

為了方便我們的開發,spring boot內建了許多有用的Filter,我們可以根據業務的需求,選擇適合業務的Filter。

三、拓展

通過前面的N篇部落格,我們會發現spring boot處理Servlet,Listener,Filter的思路大致都是一樣,對應的註解分別為@WebServlet@WebListener@WebFilter,對應的註冊Bean分別為ServletRegistrationBean,ServletListenerRegistrationBean,FilterRegistrationBean,無論哪種方式,都大大的簡化了我們的開發