callApi: function() { var vm = this vm.msg = '' vm.result = '' headers = {} headers.Authorization = 'Bearer ' + sessionStorage.getItem('accessToken'); $.ajax({ type: 'get', dataTye: 'json', url: vm.apiUrl, headers: headers, success: function(data) { vm.result = data }, error: vm.requestError }) }
在调用callApi方法时,设置了请求头的Authorization属性,其格式为:"Bearer access_token"。
由于服务端指定使用了Bearer类型的access token,所以客户端必须使用这种格式将access token传给资源服务器。
在试验这个示例时,我们一共进行了5次操作:
第1次操作:没有输入用户名和密码,直接点击[调用API]按钮,服务端返回401的状态码,表示该请求未授权。
第2次操作:输入用户名和密码,然后店点击登录按钮,登录成功。
第3次操作:点击[调用API]按钮,服务端返回200的状态码,请求成功。
第4次操作:点击[注销]链接,注销成功。
第5次操作:再次点击[调用API]按钮,服务端返回401的状态码,表示该请求未授权。
有人可能会注意到,为什么每次点击[调用API]按钮,都发起了两次请求?
这是因为当浏览器发送跨域请求时,浏览器都会先发送一个OPTIONS预请求(preflight request)给目标站点,用于确认目标站点是否接受跨域请求,如果目标站点不支持跨域请求,浏览器会提示错误:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
如果是POST请求,且数据类型(Content-Type)是application/x-www-form-urlencoded,multipart/form-data 或 text/plain中的一种,则浏览器不会发送预请求,上图的/token请求就是满足该条件的。
zepto会自动将非GET请求的Content-Type设置为application/x-www-form-urlencoded:
if (settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() != 'GET')) setHeader('Content-Type', settings.contentType || 'application/x-www-form-urlencoded') image
我们还是通过Fidder看一下第1次/api/Values请求和响应的Headers信息
请求的Headers信息,它是一次OPTIONS请求。
响应的Headers信息,Access-Control-Allow-Origin: *表示允许所有外部站点对目标站点发送跨域请求。
更多CORS的知识,请参考MDN上的说明:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
基于vue-resource实现注册、登录和API调用
基于vue-resource实现这3项功能时,沿用上面的HTML代码。
注册
更为简洁的register方法:
register: function() { this.$http.post(this.registerUrl, this.registerModel) .then((response) => { this.msg = '注册成功!' }).catch((response) => { this.msg = response.json() }) }
注意:当使用vue-resource发送注册的POST请求时,Fiddler捕获到了2次请求,第1次是由浏览器发送的OPTIONS预请求,第2次才是实际的POST请求。这和使用$.ajax时是不一样的,因为$.ajax会将非GET请求的Content-Type设置为application/x-www-form-urlencoded,而vue-resource发送POST请求的Content-Type为application/json;charset=UTF-8。
启用emulateJSON选项,可以让浏览器不发送OPTIONS预请求,有两种启用方式。
1.全局启用
Vue.http.options.emulateJSON = true
2.局部启用
this.$http.post(this.registerUrl, this.registerModel ,{ emulateJSON : true}) .then( (response) => { this.msg = '注册成功!' })
启用了emulateJSON选项后,使得POST请求的Content-Type变为application/x-www-form-urlencoded
登录和注销
登录和注销的方法: