Springboot 如何實(shí)現(xiàn)filter攔截token驗(yàn)證和跨域
Springboot filter攔截token驗(yàn)證和跨域
背景
web驗(yàn)證授權(quán)合法的一般分為下面幾種
- 使用session作為驗(yàn)證合法用戶訪問的驗(yàn)證方式
- 使用自己實(shí)現(xiàn)的token
- 使用OCA標(biāo)準(zhǔn)
在使用API接口授權(quán)驗(yàn)證時(shí),token是自定義的方式實(shí)現(xiàn)起來不需要引入其他東西,關(guān)鍵是簡單實(shí)用。
合法登陸后一般使用用戶UID+鹽值+時(shí)間戳使用多層對(duì)稱加密生成token并放入分布式緩存中設(shè)置固定的過期時(shí)間長(和session的方式有些相同),這樣當(dāng)用戶訪問時(shí)使用token可以解密獲取它的UID并據(jù)此驗(yàn)證其是否是合法的用戶。
#springboot中實(shí)現(xiàn)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驗(yàn)證攔截 * @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; //設(shè)置允許跨域的配置 // 這里填寫你允許進(jìn)行跨域的主機(jī)ip(正式上線時(shí)可以動(dòng)態(tài)配置具體允許的域名和IP) rep.setHeader("Access-Control-Allow-Origin", "*"); // 允許的訪問方法 rep.setHeader("Access-Control-Allow-Methods","POST, GET, PUT, OPTIONS, DELETE, PATCH"); // Access-Control-Max-Age 用于 CORS 相關(guān)配置的緩存 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("用戶授權(quán)認(rèn)證沒有通過!客戶端請(qǐng)求參數(shù)中無token信息"); } else { if (TokenUtil.volidateToken(token)) { resultInfo.setCode(Constant.SUCCESS); resultInfo.setMsg("用戶授權(quán)認(rèn)證通過!"); isFilter = true; } else { resultInfo.setCode(Constant.UN_AUTHORIZED); resultInfo.setMsg("用戶授權(quán)認(rèn)證沒有通過!客戶端請(qǐng)求參數(shù)token信息無效"); } } if (resultInfo.getCode() == Constant.UN_AUTHORIZED) {// 驗(yàn)證失敗 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
加上如下配置則啟動(dòng)時(shí)會(huì)根據(jù)注解加載此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; }
以上兩種方式都可以實(shí)現(xiàn)filter
跨域說明
springboot可以設(shè)置全局跨域,但是對(duì)于filter中的攔截地址并不其中作用,因此需要在dofilter中再次設(shè)置一次
區(qū)局設(shè)置跨域方式如下
方式1.在application.java中加入如下代碼
//跨域設(shè)置 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服務(wù)端設(shè)置Respone Header頭中Access-Control-Allow-Origin 2配合前臺(tái)使用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); } }
springboot配置Filter & 允許跨域請(qǐng)求
1.filter類
加注解:
@WebFilter(filterName = "authFilter", urlPatterns = "/*")
代碼如下:
package com.activiti.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; // renwenqiang @WebFilter(filterName = "authFilter", urlPatterns = "/*") public class SystemFilter implements Filter { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; response.setHeader("Access-Control-Allow-Origin","*"); System.out.println(request.getRequestURL()); filterChain.doFilter(request, servletResponse); } @Override public void destroy() { } @Override public void init(FilterConfig arg0) throws ServletException { } }
2.啟動(dòng)類
加注解:
@ServletComponentScan(basePackages = {"com.activiti.filter"})
代碼如下:
package com; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication(exclude = { org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class, org.activiti.spring.boot.SecurityAutoConfiguration.class }) @ServletComponentScan(basePackages = {"com.activiti.filter"}) public class DemoActiviti0108Application { @Bean public HibernateJpaSessionFactoryBean sessionFactory() { return new HibernateJpaSessionFactoryBean(); } public static void main(String[] args) { SpringApplication.run(DemoActiviti0108Application.class, args); } }
3.jquery ajax請(qǐng)求代碼實(shí)例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <div id="app"> <hr> <h2>模型列表</h2> <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="huizhi">繪制流程</a> <hr> <table border="1"> <tr> <td>id</td> <td>deploymentId</td> <td>name</td> <td>category</td> <td>optional</td> </tr> <tr v-for="item in models"> <td>{{ item.id }}</td> <td>{{ item.deploymentId }}</td> <td>{{ item.name }}</td> <td>{{ item.category }}</td> <td> <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >編輯</a> <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >發(fā)布</a> <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >刪除</a> </td> </tr> </table> </div> <script src="https://cdn.bootcss.com/jquery/2.2.2/jquery.js"></script> <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script> <script> new Vue({ el: '#app', data: { models: [] }, created: function () { $.ajax({ type: 'GET', url: 'http://localhost:8081/activiti/model/all', beforeSend: function() { console.log('beforeSend'); }, data:{}, dataType: "json", xhrFields: { withCredentials: false }, crossDomain: true, async: true, //jsonpCallback: "jsonpCallback",//服務(wù)端用于接收callback調(diào)用的function名的參數(shù) }).done((data) => { console.log('done'); console.log(data); this.models = data; }).fail((error) => { console.log('fail'); console.log('error'); }); } }) </script> </body> </html>
大功告成 回家睡覺 嘻嘻嘻~
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- springboot實(shí)現(xiàn)token驗(yàn)證登陸狀態(tài)的示例代碼
- SpringBoot整合JWT(JSON?Web?Token)生成token與驗(yàn)證的流程及示例
- springboot+shiro+jwtsession和token進(jìn)行身份驗(yàn)證和授權(quán)
- SpringBoot集成JWT實(shí)現(xiàn)Token登錄驗(yàn)證的示例代碼
- SpringBoot登錄驗(yàn)證token攔截器的實(shí)現(xiàn)
- 實(shí)戰(zhàn)SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證
- SpringBoot整合JWT框架,解決Token跨域驗(yàn)證問題
- SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證的流程
- SpringBoot下token短信驗(yàn)證登入登出權(quán)限操作(token存放redis,ali短信接口)
- Spring boot+VUE實(shí)現(xiàn)token驗(yàn)證的示例代碼
相關(guān)文章
java讀取其他服務(wù)接口返回的json數(shù)據(jù)示例代碼
這篇文章主要給大家介紹了關(guān)于java讀取其他服務(wù)接口返回的json數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03jedis連接池對(duì)commons-pool的封裝示例詳解
這篇文章主要為大家介紹了jedis連接池對(duì)commons-pool的封裝示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09swing中Tree與滾動(dòng)條用法實(shí)例分析
這篇文章主要介紹了swing中Tree與滾動(dòng)條用法,以實(shí)例形式分析了java基于swing實(shí)現(xiàn)圖形界面的使用技巧,需要的朋友可以參考下2015-09-09java對(duì)接支付寶支付接口開發(fā)詳細(xì)步驟
本文主要介紹了java對(duì)接支付寶支付接口開發(fā)詳細(xì)步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01springboot攔截器Interceptor的使用,你都了解嗎
springmvc 中的攔截器可以對(duì)請(qǐng)求進(jìn)行判別,在請(qǐng)求到達(dá)控制器之前,把非法的請(qǐng)求給攔截掉下面來說一說, 它在springboot中的使用,感興趣的朋友一起看看吧2021-07-07由@NotNull注解引出的關(guān)于Java空指針的控制
這是一些很容易學(xué)會(huì)的簡單技術(shù),但是對(duì)于代碼質(zhì)量和健壯性來說確實(shí)很重要。以我的經(jīng)驗(yàn),僅是第一個(gè)小技巧就已經(jīng)對(duì)改進(jìn)代碼質(zhì)量具有很大的作用了2016-09-09使用IDEA如何導(dǎo)入SpringBoot項(xiàng)目
這篇文章主要介紹了使用IDEA如何導(dǎo)入SpringBoot項(xiàng)目問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,2023-12-12