一.使用場景:
2.如接口調用過程中,每次調用都需要傳送一個token,我們怎樣去對接口進行攔截
所以本文就來講一講自己在工作中的全局解碼的實現方式:
前端編碼的方式參考前一篇隨筆:https://www.cnblogs.com/KdeS/p/12073331.html
二.定義一個Filter或者OncePerRequestFilter
這里會引入一個類 javax.servlet.http.HttpServletRequestWrapper,是一個擴展的通用接口,也就是會對request做一次包裝,我們需要繼承並重寫這個方法。
2.1 代碼部分如下
package com.grand.p1upgrade.filter; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper{ // 用於存儲請求參數 private Map<String , String[]> params = new HashMap<String, String[]>(); public MyHttpServletRequestWrapper(HttpServletRequest request) { super(request); // 把請求參數添加到我們自己的map當中 this.params.putAll(request.getParameterMap()); } public void setParameters(Map<String, Object> extraParams) { for (Map.Entry<String, Object> entry : extraParams.entrySet()) { setParameter(entry.getKey(), entry.getValue()); } } /** * 添加參數到map中 * @param name * @param value */ public void setParameter(String name, Object value) { if (value != null) { if (value instanceof String[]) { params.put(name, (String[]) value); } else if (value instanceof String) { params.put(name, new String[]{(String) value}); } else { params.put(name, new String[]{String.valueOf(value)}); } } } /** * 重寫getParameter,代表參數從當前類中的map獲取 * @param name * @return */ @Override public String getParameter(String name) { String[]values = params.get(name); if(values == null || values.length == 0) { return null; } return values[0]; } /** * 重寫getParameterValues方法,從當前類的 map中取值 * @param name * @return */ @Override public String[] getParameterValues(String name) { return params.get(name); } }
2.2 繼承OncePerRequestFilter覆蓋doFilterInternal對密碼解碼
package com.grand.p1upgrade.filter; import java.io.IOException; import java.util.Base64; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; /** * 參數過濾,對所有請求接口的請求進行攔截是否有pwd參數,有則解密,並將參數放入request.parameter中 * * @author SanLi * Created by 2689170096@qq.com/SanLi on 2018/1/28 */ //@Component public class RequestParameterFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String pwd=request.getParameter("pwd"); if(pwd!=null) { pwd= new String(Base64.getDecoder().decode(pwd), "UTF-8"); MyHttpServletRequestWrapper wrapper = new MyHttpServletRequestWrapper(request); wrapper.setParameter("pwd",pwd); /** * 1.一般filter都是一個鏈,web.xml 里面配置了幾個就有幾個。一個一個的連在一起 * request -> filter1 -> filter2 ->filter3 -> …. -> request resource. * * 2.chain.doFilter將請求轉發給過濾器鏈下一個filter , 如果沒有filter那就是你請求的資源 */ filterChain.doFilter(wrapper, response); } return; } }
2.2 繼承Filter對密碼解碼
package com.grand.p1upgrade.filter; import java.io.IOException; import java.util.Base64; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; import lombok.extern.java.Log; /** * 過濾所有的請求,包含靜態資源,如果請求cookie中含有token或請求為靜態資源,則放行請求,否則進入到登陸頁面 */ @Log @Component public class TokenFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { MyHttpServletRequestWrapper wrapper = null; String token = null; HttpServletRequest request= (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String uri = request.getRequestURI(); //參數過濾,對所有請求接口的請求進行攔截是否有pwd參數,有則解密,並將參數放入request.parameter中 String pwd=request.getParameter("pwd"); wrapper = new MyHttpServletRequestWrapper(request); if(pwd!=null) { pwd= new String(Base64.getDecoder().decode(pwd), "UTF-8"); wrapper.setParameter("pwd",pwd); } if(uri.contains("/login"))||uri.contains("/static")){ //通過,不攔截 chain.doFilter(wrapper,response); }else{ // 攔截請求,判斷cookie中是否有token,沒有則跳轉到登陸頁,有則放行 Cookie[] cookies = request.getCookies(); if(cookies!=null){ for (Cookie cookie : cookies) { if("token".equals(cookie.getName())){ // 前端傳遞過來的token包含兩部分:key,value token = cookie.getValue(); } } } // token有值,且包含"_",就通過 if(StringUtils.isNotEmpty(token)&&token.contains("_")){ chain.doFilter(wrapper,response); }else{ response.setStatus(401); // 需要權限 } } } @Override public void destroy() {} }
