为了用户登录授权、获取授权码、提交授权码及Client Secret,Cient ID等这个复杂的过程,而在第一次获得accessToken的时候附带的refreshToken。
/**
* Save token.
*/
InMemoryCache.prototype.saveToken = function(token, client, user) {
this.tokens.push({
accessToken: token.accessToken,
accessTokenExpiresAt: token.accessTokenExpiresAt,
clientId: client.clientId,
refreshToken: token.refreshToken,
refreshTokenExpiresAt: token.refreshTokenExpiresAt,
userId: user.id
});
return { accessToken: 'foobar', refreshToken: 'foobiz', client: {}, user: {} };
};
2)Postman测试
-----authorize-----
POST /oauth2/authorize?state=foobiz HTTP/1.1
Host: localhost:3000
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: 9307f9f1-2b91-ed61-cd72-137a6baa78e3
client_id=thom&response_type=code&user_id=u_thom
-----token-----
POST /oauth2/token HTTP/1.1
Host: localhost:3000
Cache-Control: no-cache
Postman-Token: 0cdb283a-903e-3907-eb80-eee630985487
Content-Type: application/x-www-form-urlencoded
client_id=thom&client_secret=nightworld&grant_type=password&username=thomseddon&password=nightworld
-----post call /api/v1/users-----
POST /api/v1/users HTTP/1.1
Host: localhost:3000
Authorization: Bearer foobar
Cache-Control: no-cache
Postman-Token: 3de36e9f-2cc7-dd46-6b82-65b5c49965da
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
-----get call /api/v1/users-----
GET /api/v1/users HTTP/1.1
Host: localhost:3000
Authorization: Bearer foobar
Cache-Control: no-cache
Postman-Token: df113160-8595-252f-ff0e-a614c3b8172b
3)Axios测试
因为跨域问题,在axios中访问:localhost:3000/api/vi/users,并不能像postman那样获得正确的结果。
我们采用的是Vue,下面是login.vue(vue-cli自动生成的框架)的部份修改代码。
-----login.vue-----
<script>
import { setCookie, getCookie } from '../assets/js/cookie.js'
export default {
data () {
return {
showLogin: true,
showRegister: false,
showTishi: false,
tishi: '',
username: '',
password: '',
newUsername: '',
newPassword: '',
devs: []
}
},
mounted () {
/* 页面挂载获取cookie,如果存在username的cookie,则跳转到主页,不需登录 */
if (getCookie('username')) {
this.$router.push('/home')
}
},
methods: {
login () {
if (this.username === '' || this.password === '') {
alert('请输入用户名或密码')
} else {
let data = { username: this.username, password: this.password }
this.$http
.get('http://localhost:3000/api/v1/users', data)
.then(res => {
console.log(res)
/* 接口的传值是(-1,该用户不存在),(0,密码错误),同时还会检测管理员账号的值 */
if (res.data === -1) {
this.tishi = '该用户不存在'
this.showTishi = true
} else if (res.data === 0) {
this.tishi = '密码输入错误'
this.showTishi = true
} else if (res.data === 'admin') {
/* 路由跳转this.$router.push */
this.$router.push('/main')
} else {
this.tishi = '登录成功'
this.showTishi = true
setCookie('username', this.username, 1000 * 60)
setTimeout(
function () {
this.$router.push('/home')
}.bind(this),
1000
)
}
})
}
}
}
}
</script>
下面是main.js修改之后的。主要是添加了Authorization的Bearer Token。
-----main.js-----
import Vue from 'vue'
import AppA from './App'
import router from './router'
import axios from 'axios'
axios.interceptors.request.use(function (config) {
const token = 'foobar' // this.$store.state.token
if (token) {
config.headers.Authorization = `Bearer ${token}`
console.log(config)
}
return config
}, function (err) {
return Promise.reject(err)
})
Vue.prototype.$http = axios
Vue.config.productionTip = false
// console.log('test')
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { AppA },
template: '<AppA/>'
})
console.log(AppA.name)
为了跨域,express后端的代码主要处理了跨域的时候,浏览器发出的options命令,这个命令不要oauth2进行鉴权。
参考如下的修改的app.js。
-----app.js-----
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var createError = require('http-errors');
var oauthserver = require('express-oauth-server');
var express = require('express');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
var mo = require('./model/model.js');
var memorymodel = new mo();
app.oauth = new oauthserver({
model: memorymodel,
grants:['password', 'authorization_code', 'refresh_token']
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(indexRouter);
app.options('*', function(req, res, next){
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Authorization,X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
/* authorize provide authorize code to clientside */
app.use('/oauth2/authorize', app.oauth.authorize(
{
authenticateHandler: {
handle: (req, res) => {
return req.body.user_id === 'u_thom';
}
}
})
);
/* get access token */
app.use('/oauth2/token', app.oauth.token());
/* authenticate protect the resource api (client side should provide token) */
app.get('/api/v1/*', app.oauth.authenticate());
app.post('/api/v1/*', app.oauth.authenticate());
app.use('/api/v1/users', usersRouter);
//app.use('/api/v1/sshports', sshportsRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;