OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,与"服务商提供商"进行互动。
(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。
授权码模式(authorization code)
简化模式(implicit)
密码模式(resource owner password credentials)
客户端模式(client credentials)
我们这边用的主要是密码模式
1.步骤如下:
(A)用户向客户端提供用户名和密码。
(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。
(C)认证服务器确认无误后,向客户端提供访问令牌。
2.客户端发出的HTTP请求,包含以下参数:
grant_type:表示授权类型,此处的值固定为"password",必选项。
username:表示用户名,必选项。
password:表示用户的密码,必选项。
scope:表示权限范围,可选项。
3.示例
1)这里是点击登录按钮触发的登录接口请求
//密码登录的按钮
passLoginBtn(){
this.$refs.passwordForm.validate((valid) => {
if (valid) {
if(this.isRememberPassword){
var date=new Date()
localStorage.setItem('userName',this.passwordForm.userName)
localStorage.setItem('password',this.passwordForm.password)
localStorage.setItem('startTime',date.getTime())
}
this.$httpLoginPost('/api/iamp-oauth2/oauth/token',{
username: 'admin',//username和password是输入框输入的值
password: '123456',
grant_type:'password',//grant_type表示授权类型,固定为"password",必选项
scope:'read write'//可读写,表示权限范围,可选项
})
.then( (res) =>{
console.log(res);
this.$store.commit('getAccessToken',res.access_token)//把token值存起来
this.getMenulist()
// this.$router.push({name:'Main'})
})
.catch( (error) =>{
console.log(error);
});
} else {
console.log('error submit!!');
return false;
}
});
},
返回的数据可以打印看一下:
这里的$httpLoginPost是我自己封装的login的post请求的方法,为什么要单独封装login呢?因为他和其他的post请求不同,他在请求的时候需要加个auth.
2)下面是我自己封装的httpRequest.js里的方法
import axios from 'axios'
import qs from 'qs'
import store from './../../store'
var http = axios.create({
baseURL: '/api',
timeout: 1000
});
axios.defaults.headers.post['Content-Type']='application/x-www=-form-urlencoded'
http.param=(data = {},contentType = 'application/x-www-form-urlencoded')=>{
return contentType === 'application/x-www-form-urlencoded' ? qs.stringify(data):(contentType ==='application/json'?JSON.stringify(data):data);
}
//http拦截器
http.interceptors.request.use(config => {
const authToken=store.state.token;
if(authToken!=''){
console.log(authToken)
config.headers['Authorization']='Bearer '+authToken;
}
return config;
}),error => {
console.log(error)
}
//登录的接口,是客户端id和客户端密码,这两个值是唯一确定的,后台给的
export function httpLoginPost(url,param={}){
return new Promise((resolve,reject)=>{
http.post(url,http.param(param),{auth:{
username: 'iamp-admin',
password: '123456'
}})
.then(response=>{
resolve(response.data)
})
.catch(err=>{
reject(err)
})
})
}
需要注意的是这里请求的时候我们加了个
{
auth:{
username: 'iamp-admin',
password: '123456'
}
}
这里的username和password是唯一且确定的,是后台给我们的,是客户端id和客户端密码。
3)上面我有说到返回的值里面我们要拿到他的token,拿到这个值有什么用呢?这个值就相当于访问令牌,我们在访问其他接口的时候就用他去访问。
所以我们需要在httpRequest.js里面添加一个请求拦截
//http拦截器
http.interceptors.request.use(config => {
const authToken=store.state.token;
if(authToken!=''){
console.log(authToken)
config.headers['Authorization']='Bearer '+authToken;
}
return config;
}),error => {
console.log(error)
}
每次请求的时候看是否有token值,有就用到请求的headers里面,没有就抛出错误,可能就会返回到登陆页面。