Springboot實現filter攔截token驗證和跨域


背景

web驗證授權合法的一般分為下面幾種

  • 使用session作為驗證合法用戶訪問的驗證方式
  • 使用自己實現的token
  • 使用OCA標准

在使用API接口授權驗證時,token是自定義的方式實現起來不需要引入其他東西,關鍵是簡單實用。

合法登陸后一般使用用戶UID+鹽值+時間戳使用多層對稱加密生成token並放入分布式緩存中設置固定的過期時間長(和session的方式有些相同),這樣當用戶訪問時使用token可以解密獲取它的UID並據此驗證其是否是合法的用戶。

springboot中實現filter

  • 一種是注解filter
  • 一種是顯示的硬編碼注冊filter

先有filter

import javax.servlet.annotation.WebFilter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import springfox.documentation.spring.web.json.Json;

import com.alibaba.fastjson.JSON;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;



/***************
 * token驗證攔截
 * @author bamboo zjcjava@163.com
 * @time 2017-08-01
 */
@Component
//@WebFilter(urlPatterns = { "/api/v/*" }, filterName = "tokenAuthorFilter")
public class TokenAuthorFilter implements Filter {

    private static Logger logger = LoggerFactory
            .getLogger(TokenAuthorFilter.class);

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse rep = (HttpServletResponse) response;

        //設置允許跨域的配置
        // 這里填寫你允許進行跨域的主機ip(正式上線時可以動態配置具體允許的域名和IP)
        rep.setHeader("Access-Control-Allow-Origin", "*");
        // 允許的訪問方法
        rep.setHeader("Access-Control-Allow-Methods","POST, GET, PUT, OPTIONS, DELETE, PATCH");
        // Access-Control-Max-Age 用於 CORS 相關配置的緩存
        rep.setHeader("Access-Control-Max-Age", "3600");
        rep.setHeader("Access-Control-Allow-Headers","token,Origin, X-Requested-With, Content-Type, Accept");


        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        String token = req.getHeader("token");//header方式
        ResultInfo resultInfo = new ResultInfo();
        boolean isFilter = false;


        String method = ((HttpServletRequest) request).getMethod();
        if (method.equals("OPTIONS")) {
            rep.setStatus(HttpServletResponse.SC_OK);
        }else{


            if (null == token || token.isEmpty()) {
                resultInfo.setCode(Constant.UN_AUTHORIZED);
                resultInfo.setMsg("用戶授權認證沒有通過!客戶端請求參數中無token信息");
            } else {
                if (TokenUtil.volidateToken(token)) {
                    resultInfo.setCode(Constant.SUCCESS);
                    resultInfo.setMsg("用戶授權認證通過!");
                    isFilter = true;
                } else {
                    resultInfo.setCode(Constant.UN_AUTHORIZED);
                    resultInfo.setMsg("用戶授權認證沒有通過!客戶端請求參數token信息無效");
                }
            }
            if (resultInfo.getCode() == Constant.UN_AUTHORIZED) {// 驗證失敗
                PrintWriter writer = null;
                OutputStreamWriter osw = null;
                try {
                    osw = new OutputStreamWriter(response.getOutputStream(),
                            "UTF-8");
                    writer = new PrintWriter(osw, true);
                    String jsonStr = JSON.toJSONString(resultInfo);
                    writer.write(jsonStr);
                    writer.flush();
                    writer.close();
                    osw.close();
                } catch (UnsupportedEncodingException e) {
                    logger.error("過濾器返回信息失敗:" + e.getMessage(), e);
                } catch (IOException e) {
                    logger.error("過濾器返回信息失敗:" + e.getMessage(), e);
                } finally {
                    if (null != writer) {
                        writer.close();
                    }
                    if (null != osw) {
                        osw.close();
                    }
                }
                return;
            }

            if (isFilter) {
            logger.info("token filter過濾ok!");
            chain.doFilter(request, response);
            }
        }


    }

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

    }

}

注解配置filter

加上如下配置則啟動時會根據注解加載此filter 
@WebFilter(urlPatterns = { “/api/*” }, filterName = “tokenAuthorFilter”)

硬編碼注冊filter

在application.java中加入如下代碼

 //注冊filter
    @Bean  
    public FilterRegistrationBean  filterRegistrationBean() {  
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();  
        TokenAuthorFilter tokenAuthorFilter = new TokenAuthorFilter();  
        registrationBean.setFilter(tokenAuthorFilter);  
        List<String> urlPatterns = new ArrayList<String>();  
        urlPatterns.add("/api/*");
        registrationBean.setUrlPatterns(urlPatterns);  
        return registrationBean;  
    }  

以上兩種方式都可以實現filter

跨域說明

springboot可以設置全局跨域,但是對於filter中的攔截地址並不其中作用,因此需要在dofilter中再次設置一次

區局設置跨域方式如下

方式1.在application.java中加入如下代碼

//跨域設置
    private CorsConfiguration buildConfig() {  
        CorsConfiguration corsConfiguration = new CorsConfiguration();  
        corsConfiguration.addAllowedOrigin("*");  
        corsConfiguration.addAllowedHeader("*");  
        corsConfiguration.addAllowedMethod("*");  



        return corsConfiguration;  
    }  

    /** 
     * 跨域過濾器 
     * @return 
     */  
    @Bean  
    public CorsFilter corsFilter() {  
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();  
        source.registerCorsConfiguration("/**", buildConfig()); // 4  
        return new CorsFilter(source);  
    }  

方式2.配置注解

必須集成WebMvcConfigurerAdapter類

/**********
 * 跨域 CORS:使用 方法3
 * 方法:
    1服務端設置Respone Header頭中Access-Control-Allow-Origin
    2配合前台使用jsonp
    3繼承WebMvcConfigurerAdapter 添加配置類
    http://blog.csdn.net/hanghangde/article/details/53946366
 * @author xialeme
 *
 */
@Configuration  
public class CorsConfig extends WebMvcConfigurerAdapter{  

   /* @Override  
    public void addCorsMappings(CorsRegistry registry) {  
        registry.addMapping("/**")  
                .allowedOrigins("*")  
                .allowCredentials(true)  
                .allowedMethods("GET", "POST", "DELETE", "PUT")  
                .maxAge(3600);  
    }  */

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1
        corsConfiguration.addAllowedHeader("*"); // 2
        corsConfiguration.addAllowedMethod("*"); // 3
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 4
        return new CorsFilter(source);
    }


} 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM