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í)間戳使用多層對稱加密生成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)證沒有通過!客戶端請求參數(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)證沒有通過!客戶端請求參數(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è)置全局跨域,但是對于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 & 允許跨域請求
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請求代碼實(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一維數(shù)組及練習(xí)題實(shí)例
在本篇文章里小編給大家整理了關(guān)于java一維數(shù)組及練習(xí)題的相關(guān)知識(shí)點(diǎn)和實(shí)例代碼,有需要的朋友們跟著學(xué)習(xí)下。2019-07-07
IDEA 開發(fā)多項(xiàng)目依賴的方法(圖文)
這篇文章主要介紹了IDEA 開發(fā)多項(xiàng)目依賴的方法(圖文),本文講一下關(guān)于使用IntelliJ IDEA基于Maven創(chuàng)建多模塊項(xiàng)目的實(shí)際開發(fā),非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-10-10
詳解微信開發(fā)之a(chǎn)ccess_token之坑
access_token分類一是普通access_token,二是網(wǎng)頁授權(quán)access_token。這篇文章主要介紹了詳解微信開發(fā)之a(chǎn)ccess_token之坑,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10
java解析dbf之通過javadbf包生成和讀取dbf文件
這篇文章主要介紹了java通過javadbf讀取和生成DBF文件的方法,大家參考使用吧2014-01-01

