前言
假設客戶端在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