fetch 设置header请求的header怎么授权

使用Authorization_Code获取Access_Token
本步骤的作用:
通过用户验证登录和授权,获取Access Token,为下一步获取用户的OpenID做准备;
同时,Access Token是应用在调用OpenAPI访问和修改用户数据时必须传入的参数。
移动端应用可以直接获得AccessToken,请参考
本步骤在整个流程中的位置:
即server-side模式,是的一种模式,又称Web Server Flow;
适用于需要从web server访问的应用,例如Web/wap网站。
其授权验证流程示意图如下(图片来源:
对于应用而言,需要进行两步:
1. 获取Authorization Code;
2. 通过Authorization Code获取Access Token
请求地址:
/oauth2.0/authorize
https://graph./moc2/authorize
请求方法:
请求参数:
请求参数请包含如下内容:
response_type
授权类型,此值固定为“code”。
申请QQ登录成功后,分配给应用的appid。
redirect_uri
成功授权后的回调地址,必须是注册appid时填写的主域名下的地址,建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。
client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
请求用户授权时向用户显示的可进行授权的列表。
可填写的值是中列出的接口,以及一些动作型的授权(目前仅有:do_like),如果要填写多个接口名称,请用逗号隔开。
例如:scope=get_user_info,list_album,upload_pic,do_like
不传则默认请求对接口get_user_info进行授权。
建议控制授权项的数量,只传入必要的接口名称,因为授权项越多,用户越可能拒绝进行任何授权。
仅PC网站接入时使用。
用于展示的样式。不传则默认展示为PC下的样式。
如果传入“mobile”,则展示为mobile端下的样式。
仅WAP网站接入时使用。
QQ登录页面版本(1:wml版本; 2:xhtml版本),默认值为1。
返回说明:
1. 如果用户成功登录并授权,则会跳转到指定的回调地址,并在redirect_uri地址后带上Authorization Code和原始的state值。如:
PC网站:/demo/index.jsp?code=9A5F************************06AF&state=test
WAP网站:http://open./demo/index.jsp?code=9A5F************************06AF&state=test
注意:此code会在10分钟内过期。
2. 如果用户在登录授权过程中取消登录流程,对于PC网站,登录页面直接关闭;对于WAP网站,同样跳转回指定的回调地址,并在redirect_uri地址后带上usercancel参数和原始的state值,其中usercancel值为非零,如:
http://open./demo/index.jsp?usercancel=1&state=test
错误码说明:
接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。
PC网站接入时,错误码详细信息请参见:。
WAP网站接入时,错误码详细信息请参见:。
请求地址:
PC网站:/oauth2.0/token
WAP网站:https://graph./moc2/token
请求方法:
请求参数:
请求参数请包含如下内容:
grant_type
授权类型,此值固定为“authorization_code”。
申请QQ登录成功后,分配给网站的appid。
client_secret
申请QQ登录成功后,分配给网站的appkey。
上一步返回的authorization code。
如果用户成功登录并授权,则会跳转到指定的回调地址,并在URL中带上Authorization Code。
例如,回调地址为/my.php,则跳转到:
/my.php?code=520DD95263C1CFEA087******
注意此code会在10分钟内过期。
redirect_uri
与上面一步中传入的redirect_uri保持一致。
返回说明:
如果成功返回,即可在返回包中获取到Access Token。
返回如下字符串:access_token=FE04************************CCE2&expires_in=7776000。
expires_in是该access token的有效期,单位为秒。
错误码说明:
接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。
PC网站接入时,错误码详细信息请参见:。
WAP网站接入时,错误码详细信息请参见:。
Access_Token的有效期默认是3个月,过期后需要用户重新授权才能获得新的Access_Token。本步骤可以实现授权自动续期,避免要求用户再次授权的操作,提升用户体验。
请求地址:
PC网站:/oauth2.0/token
WAP网站:https://graph./moc2/token
请求方法:
请求参数:
请求参数请包含如下内容:
grant_type
授权类型,在本步骤中,此值为“refresh_token”。
申请QQ登录成功后,分配给网站的appid。
client_secret
申请QQ登录成功后,分配给网站的appkey。
refresh_token
在Step 2中,返回的refres_token。
返回说明:
如果成功返回,即可在返回包中获取到Access Token。 如:
access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14。
access_token
授权令牌,Access_Token。
expires_in
该access token的有效期,单位为秒。
refresh_token
在授权自动续期步骤中,获取新的Access_Token时需要提供的参数。
错误码说明:
接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。
PC网站接入时,错误码详细信息请参见:。
WAP网站接入时,错误码详细信息请参见:。
移动端应用可以直接获得AccessToken,请参考。点击阅读原文
React Native 网络请求封装:使用Promise封装fetch请求
5月12日 发布,来源:
React Native中虽然也内置了XMLHttpRequest 网络请求API(也就是俗称的ajax),但XMLHttpRequest 是一个设计粗糙的 API,不符合职责分离的原则,配置和调用方式非常混乱,而且基于事件的异步模型写起来也没有现代的 Promise 友好。而Fetch 的出现就是为了解决 XHR 的问题,所以React Native官方推荐使用Fetch API。
fetch请求示例如下:
return fetch('http://facebook.github.io/react-native/movies.json')
.then((response) =& response.json())
.then((responseJson) =& {
return responseJson.
.catch((error) =& {
console.error(error);
Fetch API的详细介绍及使用说明请参考如下文章:
使用Promise封装fetch请求
由于在项目中很多地方都需要用到网络请求,为了使用上的方便,使用ES6的Promise来封装fetch网络请求,代码如下:
let common_url = 'http://192.168.1.1:8080/'; //服务器地址
let token = '';
* @param url 接口地址
* @param method 请求方法:GET、POST,只能大写
* @param [params=''] body的请求参数,默认为空
* @return 返回Promise
function fetchRequest(url, method, params = ''){
let header = {
"Content-Type": "application/charset=UTF-8",
"accesstoken":token //用户登陆后返回的token,某些涉及用户数据的接口需要在header中加上token
console.log('request url:',url,params); //打印请求参数
if(params == ''){ //如果网络请求中带有参数
return new Promise(function (resolve, reject) {
fetch(common_url + url, {
method: method,
headers: header
}).then((response) =& response.json())
.then((responseData) =& {
console.log('res:',url,responseData); //网络请求成功返回的数据
resolve(responseData);
.catch( (err) =& {
console.log('err:',url, err); //网络请求失败返回的数据
reject(err);
}else{ //如果网络请求中没有参数
return new Promise(function (resolve, reject) {
fetch(common_url + url, {
method: method,
headers: header,
body:JSON.stringify(params) //body参数,通常需要转换成字符串后服务器才能解析
}).then((response) =& response.json())
.then((responseData) =& {
console.log('res:',url, responseData); //网络请求成功返回的数据
resolve(responseData);
.catch( (err) =& {
console.log('err:',url, err); //网络请求失败返回的数据
reject(err);
使用fetch请求,如果服务器返回的中文出现了乱码,则可以在服务器端设置如下代码解决: produces="text/charset=UTF-8"
fetchRequest使用如下:
fetchRequest('app/book','GET')
.then( res=&{
//请求成功
if(res.header.statusCode == 'success'){
//这里设定服务器返回的header中statusCode为success时数据返回成功
//服务器返回异常,设定服务器返回的异常信息保存在 header.msgArray[0].desc
console.log(res.header.msgArray[0].desc);
}).catch( err=&{
//请求失败
POST请求:
let params = {
username:'admin',
password:'123456'
fetchRequest('app/signin','POST',params)
.then( res=&{
//请求成功
if(res.header.statusCode == 'success'){
//这里设定服务器返回的header中statusCode为success时数据返回成功
//服务器返回异常,设定服务器返回的异常信息保存在 header.msgArray[0].desc
console.log(res.header.msgArray[0].desc);
}).catch( err=&{
//请求失败
fetch超时处理
由于原生的Fetch API 并不支持timeout属性,如果项目中需要控制fetch请求的超时时间,可以对fetch请求进一步封装实现timeout功能,代码如下:
fetchRequest超时处理封装
* 让fetch也可以timeout
* timeout不是请求连接超时的含义,它表示请求的response时间,包括请求的连接、服务器处理及服务器响应回来的时间
* fetch的timeout即使超时发生了,本次请求也不会被abort丢弃掉,它在后台仍然会发送到服务器端,只是本次请求的响应内容被丢弃而已
* @param fetch_promise fetch请求返回的Promise
* @param [timeout=10000] 单位:毫秒,这里设置默认超时时间为10秒
* @return 返回Promise
function timeout_fetch(fetch_promise,timeout = 10000) {
let timeout_fn = null;
//这是一个可以被reject的promise
let timeout_promise = new Promise(function(resolve, reject) {
timeout_fn = function() {
reject('timeout promise');
//这里使用Promise.race,以最快 resolve 或 reject 的结果来传入后续绑定的回调
let abortable_promise = Promise.race([
fetch_promise,
timeout_promise
setTimeout(function() {
timeout_fn();
}, timeout);
return abortable_
let common_url = 'http://192.168.1.1:8080/'; //服务器地址
let token = '';
* @param url 接口地址
* @param method 请求方法:GET、POST,只能大写
* @param [params=''] body的请求参数,默认为空
* @return 返回Promise
function fetchRequest(url, method, params = ''){
let header = {
"Content-Type": "application/charset=UTF-8",
"accesstoken":token //用户登陆后返回的token,某些涉及用户数据的接口需要在header中加上token
console.log('request url:',url,params); //打印请求参数
if(params == ''){ //如果网络请求中带有参数
return new Promise(function (resolve, reject) {
timeout_fetch(fetch(common_url + url, {
method: method,
headers: header
})).then((response) =& response.json())
.then((responseData) =& {
console.log('res:',url,responseData); //网络请求成功返回的数据
resolve(responseData);
.catch( (err) =& {
console.log('err:',url, err); //网络请求失败返回的数据
reject(err);
}else{ //如果网络请求中没有参数
return new Promise(function (resolve, reject) {
timeout_fetch(fetch(common_url + url, {
method: method,
headers: header,
body:JSON.stringify(params) //body参数,通常需要转换成字符串后服务器才能解析
})).then((response) =& response.json())
.then((responseData) =& {
console.log('res:',url, responseData); //网络请求成功返回的数据
resolve(responseData);
.catch( (err) =& {
console.log('err:',url, err); //网络请求失败返回的数据
reject(err);
加入超时处理的fetchRequest网络请求的使用方法跟没加入超时处理一样。
对于fetch网络请求的超时处理的封装参考下面这篇文章而写:
明天提醒我
我要该,理由是:
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
扫扫下载 App标签:至少1个,最多5个
首先声明一下,本文不是要讲解fetch的具体用法,不清楚的可以参考。
说道fetch就不得不提XMLHttpRequest了,XHR在发送web请求时需要开发者配置相关请求信息和成功后的回调,尽管开发者只关心请求成功后的业务处理,但是也要配置其他繁琐内容,导致配置和调用比较混乱,也不符合关注分离的原则;fetch的出现正是为了解决XHR存在的这些问题。例如下面代码:
fetch(url).then(function(response) {
return response.json();
}).then(function(data) {
console.log(data);
}).catch(function(e) {
console.log("Oops, error");
上面这段代码让开发者只关注请求成功后的业务逻辑处理,其他的不用关心,相当简单;也比较符合现代Promise形式,比较友好。
fetch是基于Promise设计的,从上面代码也能看得出来,这就要求fetch要配合Promise一起使用。正是这种设计,fetch所带来的优点正如总结的一样:
语法简单,更加语义化
基于标准的Promise实现,支持async/await
使用可以方便同构
不过话说回来,fetch虽然有很多优点,但是使用fetch来进行项目开发时,也是有一些常见问题的,下面就来说说fetch使用的常见问题。
fetch兼容性
fetch是相对较新的技术,当然就会存在浏览器兼容性的问题,借用上面应用文章的一幅图加以说明fetch在各种浏览器的原生支持情况:
从上图可以看出,在各个浏览器低版本的情况下都是不被支持的。
那么问题来了,如何在所有浏览器中通用fetch呢,当然就要考虑fetch的polyfill了。
上面说过,fetch是基于Promise来实现的,所以在低版本浏览器中Promise可能也未被原生支持,所以还需要Promise的polyfill;大多数情况下,实现fetch的polyfill需要涉及到的:
promise的polyfill,例如es6-promise、babel-polyfill提供的promise实现。
fetch的polyfill实现,例如isomorphic-fetch和whatwg-fetch
这样是否就可以安全的使用fetch来进行前后端通信了?上面说了在大多数情况下是这样,但是IE8/9则比较特殊:IE8它使用的是ES3,而IE9则对ES5部分支持。这种情况下还需要ES5的polyfill 支持了。
上述有关promise的polyfill实现,需要说明的是:
babel-runtime是不能作为Promise的polyfill的实现的,否则在IE8/9下使用fetch会报Promise未定义。为什么?我想大家猜到了,因为babel-runtime实现的polyfill是局部实现而不是全局实现,fetch底层实现用到Promise就是从全局中去取的,拿不到这报上述错误。
另外,顺便补充一下fetch的polyfill实现思路是:
首先判断浏览器是否原生支持fetch,否则结合Promise使用XMLHttpRequest的方式来实现;这正是的实现思路,而同构应用中使用的,其客户端fetch的实现是直接require whatwg-fetch来实现的。
fetch默认不携带cookie
fetch发送请求默认是不发送cookie的,不管是同域还是跨域;那么问题就来了,对于那些需要权限验证的请求就可能无法正常获取数据,这时可以配置其credentials项,其有3个值:
omit: 默认值,忽略cookie的发送
same-origin: 表示cookie只能同域发送,不能跨域发送
cookie既可以同域发送,也可以跨域发送
credentials所表达的含义,其实与XHR2中的withCredentials属性类似,表示请求是否携带cookie;具体可以参考阮一峰老师的中withCredentials一节的介绍;
这样,若要fetch请求携带cookie信息,只需设置一下credentials选项即可,例如fetch(url, {credentials: 'include'});
另外补充一点:
fetch默认对服务端通过Set-Cookie头设置的cookie也会忽略,若想选择接受来自服务端的cookie信息,也必须要配置credentials选项;
fetch请求对某些错误http状态不会reject
这主要是由fetch返回promise导致的,因为fetch返回的promise在某些错误的http状态下如400、500等不会reject,相反它会被resolve;只有网络错误会导致请求不能完成时,fetch 才会被 reject;所以一般会对fetch请求做一层封装,例如下面代码所示:
function checkStatus(response) {
if (response.status &= 200 && response.status & 300) {
const error = new Error(response.statusText);
error.response =
function parseJSON(response) {
return response.json();
export default function request(url, options) {
let opt = options||{};
return fetch(url, {credentials: 'include', ...opt})
.then(checkStatus)
.then(parseJSON)
.then((data) =& ( data ))
.catch((err) =& ( err ));
fetch不支持超时timeout处理
用过fetch的都知道,fetch不像大多数ajax库那样对请求设置超时timeout,它没有有关请求超时的feature,这一点比较蛋疼。所以在fetch标准添加超时feature之前,都需要polyfill该特性。
实际上,我们真正需要的是abort(), timeout可以通过timeout+abort方式来实现,起到真正超时丢弃当前的请求。
而在目前的fetch指导规范中,fetch并不是一个具体实例,而只是一个方法;其返回的promise实例根据Promise指导规范标准是不能abort的,也不能手动改变promise实例的状态,只能由内部来根据请求结果来改变promise的状态。
既然不能手动控制fetch方法执行后返回的promise实例状态,那么是不是可以创建一个可以手动控制状态的新Promise实例呢。所以:
实现fetch的timeout功能,其思想就是新创建一个可以手动控制promise状态的实例,根据不同情况来对新promise实例进行resolve或者reject,从而达到实现timeout的功能;
根据github上上的讨论,目前可以有两种不同的解决方法:
方法一:单纯setTimeout方式
var oldFetchfn = //拦截原始的fetch方法
window.fetch = function(input, opts){//定义新的fetch方法,封装原有的fetch方法
return new Promise(function(resolve, reject){
var timeoutId = setTimeout(function(){
reject(new Error("fetch timeout"))
}, opts.timeout);
oldFetchfn(input, opts).then(
clearTimeout(timeoutId);
resolve(res)
clearTimeout(timeoutId);
reject(err)
当然在上面基础上可以模拟类似XHR的abort功能:
var oldFetchfn =
window.fetch = function(input, opts){
return new Promise(function(resolve, reject){
var abort_promise = function(){
reject(new Error("fetch abort"))
var p = oldFetchfn(input, opts).then(resolve, reject);
p.abort = abort_
方法二:利用Promise.race方法
Promise.race方法接受一个promise实例数组参数,表示多个promise实例中任何一个最先改变状态,那么race方法返回的promise实例状态就跟着改变,具体可以参考。
var oldFetchfn = //拦截原始的fetch方法
window.fetch = function(input, opts){//定义新的fetch方法,封装原有的fetch方法
var fetchPromise = oldFetchfn(input, opts);
var timeoutPromise = new Promise(function(resolve, reject){
setTimeout(()=&{
reject(new Error("fetch timeout"))
}, opts.timeout)
retrun Promise.race([fetchPromise, timeoutPromise])
最后,对fetch的timeout的上述实现方式补充几点:
timeout不是请求连接超时的含义,它表示请求的response时间,包括请求的连接、服务器处理及服务器响应回来的时间;
fetch的timeout即使超时发生了,本次请求也不会被abort丢弃掉,它在后台仍然会发送到服务器端,只是本次请求的响应内容被丢弃而已;
fetch不支持JSONP
fetch是与服务器端进行异步交互的,而JSONP是外链一个javascript资源,并不是真正ajax,所以fetch与JSONP没有什么直接关联,当然至少目前是不支持JSONP的。
这里我们把JSONP与fetch关联在一起有点差强人意,fetch只是一个ajax库,我们不可能使fetch支持JSONP;只是我们要实现一个JSONP,只不过这个JSONP的实现要与fetch的实现类似,即基于Promise来实现一个JSONP;而其外在表现给人感觉是fetch支持JSONP一样;
目前比较成熟的开源JSONP实现给我们提供了解决方案,想了解可以自行前往。不过再次想唠叨一下其JSONP的实现步骤,因为在本人面试的前端候选人中大部分人对JSONP的实现语焉不详;
使用它非常简单,首先需要用npm安装fetch-jsonp
npm install fetch-jsonp --save-dev
然后在像下面一样使用:
fetchJsonp('/users.jsonp', {
timeout: 3000,
jsonpCallback: 'custom_callback'
.then(function(response) {
return response.json()
}).catch(function(ex) {
console.log('parsing failed', ex)
fetch不支持progress事件
XHR是原生支持progress事件的,例如下面代码这样:
var xhr = new XMLHttpRequest()
xhr.open('POST', '/uploads')
xhr.onload = function() {}
xhr.onerror = function() {}
function updateProgress (event) {
if (event.lengthComputable) {
var percent = Math.round((event.loaded / event.total) * 100)
console.log(percent)
xhr.upload.onprogress =updateP //上传的progress事件
xhr.onprogress = updateP //下载的progress事件
xhr.send();
但是fetch是不支持有关progress事件的;不过可喜的是,根据fetch的指导规范标准,其内部设计实现了Request和Response类;其中Response封装一些方法和属性,通过Response实例可以访问这些方法和属性,例如response.json()、response.body等等;
值得关注的地方是,response.body是一个可读字节流对象,其实现了一个getRender()方法,其具体作用是:
getRender()方法用于读取响应的原始字节流,该字节流是可以循环读取的,直至body内容传输完成;
因此,利用到这点可以模拟出fetch的progress,具体可以参考这篇文章。
代码实现如下,在线demo请参考。
// fetch() returns a promise that resolves once headers have been received
fetch(url).then(response =& {
// response.body is a readable stream.
// Calling getReader() gives us exclusive access to the stream's content
var reader = response.body.getReader();
var bytesReceived = 0;
// read() returns a promise that resolves when a value has been received
reader.read().then(function processResult(result) {
// Result objects contain two properties:
- true if the stream has already given you all its data.
// value - some data. Always undefined when done is true.
if (result.done) {
console.log("Fetch complete");
// result.value for fetch streams is a Uint8Array
bytesReceived += result.value.
console.log('Received', bytesReceived, 'bytes of data so far');
// Read some more, and call this function again
return reader.read().then(processResult);
另外,github上也有使用Promise+XHR结合的方式实现类fetch的progress效果(当然这跟fetch完全不搭边)可以参考,具体代码如下:
function fetchProgress(url, opts={}, onProgress){
return new Promise(funciton(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.open(opts.method || 'get', url);
for(var key in opts.headers || {}){
xhr.setRequestHeader(key, opts.headers[key]);
xhr.onload = e =& resolve(e.target.responseText)
xhr.onerror =
if (xhr.upload && onProgress){
xhr.upload.onprogress = onP //上传
if ('onprogerss' in xhr && onProgress){
xhr.onprogress = onP //下载
xhr.send(opts.body)
fetchProgress('/upload').then(console.log)
fetch跨域问题
既然是ajax库,就不可避免与跨域扯上关系;XHR2是支持跨域请求的,只不过要满足浏览器端支持CORS,服务器通过Access-Control-Allow-Origin来允许指定的源进行跨域,仅此一种方式。
与XHR2一样,fetch也是支持跨域请求的,只不过其跨域请求做法与XHR2一样,需要客户端与服务端支持;另外,fetch还支持一种跨域,不需要服务器支持的形式,具体可以通过其mode的配置项来说明。
fetch的mode配置项有3个值,如下:
same-origin:该模式是不允许跨域的,它需要遵守同源策略,否则浏览器会返回一个error告知不能跨域;其对应的response type为basic。
cors: 该模式支持跨域请求,顾名思义它是以CORS的形式跨域;当然该模式也可以同域请求不需要后端额外的CORS支持;其对应的response type为cors。
no-cors: 该模式用于跨域请求但是服务器不带CORS响应头,也就是服务端不支持CORS;这也是fetch的特殊跨域请求方式;其对应的response type为opaque。
针对跨域请求,cors模式是常见跨域请求实现,但是fetch自带的no-cors跨域请求模式则较为陌生,该模式有一个比较明显的特点:
该模式允许浏览器发送本次跨域请求,但是不能访问响应返回的内容,这也是其response type为opaque透明的原因。
这与&img/&发送的请求类似,只是该模式不能访问响应的内容信息;但是它可以被其他APIs进行处理,例如ServiceWorker。另外,该模式返回的repsonse可以在Cache API中被存储起来以便后续的对它的使用,这点对script、css和图片的CDN资源是非常合适的,因为这些资源响应头中都没有CORS头。
总的来说,fetch的跨域请求是使用CORS方式,需要浏览器和服务端的支持。
0 收藏&&|&&15
你可能感兴趣的文章
9 收藏,807
496 收藏,71.3k
3 收藏,764
本作品采用 署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可
分享到微博?
技术专栏,帮你记录编程中的点滴,提升你对技术的理解收藏感兴趣的文章,丰富自己的知识库
明天提醒我
我要该,理由是:
扫扫下载 App}

我要回帖

更多关于 fetch token header 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信