# 鉴权
- session/cookie
// cookie.js
const http = require("http")
const session = {}
http.createServer((req, res) => {
观察cookie存在
console.log('cookie:', req.headers.cookie)
const sessionKey = 'sid'
const cookie = req.headers.cookie
if(cookie && cookie.indexOf(sessionKey) > -1 ){
res.end('Come Back ')
// 简略写法未必具有通用性
const pattern = new RegExp(`${sessionKey}=([^;]+);?\s*`)
const sid = pattern.exec(cookie)[1]
console.log('session:',sid ,session ,session[sid])
} else {
const sid = (Math.random() * 99999999).toFixed()
// 设置cookie
res.setHeader('Set-Cookie', `${sessionKey}=${sid};`)
session[sid] = {name : 'laowang'}
res.end('Hello')
}
res.end('hello cookie!!')
}).listen(3000)
koa使用中间件
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<div>
<input v-model="username">
<input v-model="password">
</div>
<div>
<button v-on:click="login">Login</button>
<button v-on:click="logout">Logout</button>
<button v-on:click="getUser">GetUser</button>
</div>
<div>
<button onclick="document.getElementById('log').innerHTML = ''">Clear Log</button>
</div>
</div>
<h6 id="log"></h6>
</div>
<script>
// axios.defaults.baseURL = 'http://localhost:3000'
axios.defaults.withCredentials = true
axios.interceptors.response.use(
response => {
document.getElementById('log').append(JSON.stringify(response.data))
return response;
}
);
var app = new Vue({
el: '#app',
data: {
username: 'test',
password: 'test'
},
methods: {
async login() {
await axios.post('/login', {
username: this.username,
password: this.password
})
},
async logout() {
await axios.post('/logout')
},
async getUser() {
await axios.get('/getUser')
}
}
});
</script>
</body>
</html>
const Koa = require('koa')
const router = require('koa-router')()
const session = require('koa-session')
// const cors = require('koa2-cors')
const bodyParser = require('koa-bodyparser')
const static = require('koa-static')
const app = new Koa();
//配置session的中间件
// app.use(cors({
// credentials: true
// }))
app.keys = ['some secret'];
app.use(static(__dirname + '/'));
app.use(bodyParser())
app.use(session(app));
app.use((ctx, next) => {
if (ctx.url.indexOf('login') > -1) {
next()
} else {
console.log('session', ctx.session.userinfo)
if (!ctx.session.userinfo) {
ctx.body = {
message: "登录失败"
}
} else {
next()
}
}
})
router.post('/login', async (ctx) => {
const {
body
} = ctx.request
console.log('body',body)
//设置session
ctx.session.userinfo = body.username;
ctx.body = {
message: "登录成功"
}
})
router.post('/logout', async (ctx) => {
//设置session
delete ctx.session.userinfo
ctx.body = {
message: "登出系统"
}
})
router.get('/getUser', async (ctx) => {
ctx.body = {
message: "获取数据成功",
userinfo: ctx.session.userinfo
}
})
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);
使用redis存储数据
const koa = require('koa')
const app = new koa()
const session = require('koa-session')
const redisStore = require('koa-redis')
const redis = require('redis')
const redisClient = redis.createClient(6379, 'localhost')
const wrapper = require('co-redis')
//让redis支持promsie形式
const client = wrapper(redisClient)
app.keys = ['some secret']
const SESS_CONFIG = {
key: 'kkb:sess', // 名
// maxAge: 8640000, // 有效期
// httpOnly: true, // 服务器有效
// signed: true // 签名
store: redisStore({ client })
}
app.use(session(SESS_CONFIG, app))
app.use(ctx => {
// 查看redis
redisClient.keys('*',(err,keys) => {
console.log('keys:',keys)
keys.forEach(key => {
redisClient.get(key, (err,val) => {
console.log(val)
})
})
})
if (ctx.path === '/favicon.ico') return
let n = ctx.session.count || 0
ctx.session.count = ++n
ctx.body = '第' + n + '次访问'
})
app.listen(3000)
- token
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<div>
<input v-model="username" />
<input v-model="password" />
</div>
<div>
<button v-on:click="login">Login</button>
<button v-on:click="logout">Logout</button>
<button v-on:click="getUser">GetUser</button>
</div>
<div>
<button @click="logs=[]">Clear Log</button>
</div>
<!-- 日志 -->
<ul>
<li v-for="(log,idx) in logs" :key="idx">
{{ log }}
</li>
</ul>
</div>
<script>
axios.interceptors.request.use(
config => {
const token = window.localStorage.getItem("token");
if (token) {
// 判断是否存在token,如果存在的话,则每个http header都加上token
// Bearer是JWT的认证头部信息
config.headers.common["Authorization"] = "Bearer " + token;
}
return config;
},
err => {
return Promise.reject(err);
}
);
axios.interceptors.response.use(
response => {
app.logs.push(JSON.stringify(response.data));
return response;
},
err => {
app.logs.push(JSON.stringify(response.data));
return Promise.reject(err);
}
);
var app = new Vue({
el: "#app",
data: {
username: "test",
password: "test",
logs: []
},
methods: {
async login() {
const res = await axios.post("/login-token", {
username: this.username,
password: this.password
});
localStorage.setItem("token", res.data.token);
},
async logout() {
localStorage.removeItem("token");
},
async getUser() {
await axios.get("/getUser-token");
}
}
});
</script>
</body>
</html>
const Koa = require('koa')
const router = require('koa-router')()
const static = require('koa-static')
const bodyParser = require('koa-bodyparser')
const app = new Koa();
const jwt = require("jsonwebtoken");
const jwtAuth = require("koa-jwt");
const secret = "it's a secret";
app.use(bodyParser())
app.use(static(__dirname + '/'));
router.post("/login-token", async ctx => {
const { body } = ctx.request;
//登录逻辑,略
//设置session
const userinfo = body.username;
ctx.body = {
message: "登录成功",
user: userinfo,
// 生成 token 返回给客户端
token: jwt.sign(
{
data: userinfo,
// 设置 token 过期时间,一小时后,秒为单位
exp: Math.floor(Date.now() / 1000) + 60 * 60
},
secret
)
};
});
router.get(
"/getUser-token",
jwtAuth({
secret
}),
async ctx => {
// 验证通过,state.user
console.log(ctx.state.user);
//获取session
ctx.body = {
message: "获取数据成功",
userinfo: ctx.state.user.data
};
}
)
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000)
- oauth 第三方登录
const Koa = require('koa')
const router = require('koa-router')()
const static = require('koa-static')
const app = new Koa();
const axios = require('axios')
const querystring = require('querystring')
app.use(static(__dirname + '/'));
const config = {
client_id: 'xxxx',
client_secret: 'xxxxxxxxxx'
}
router.get('/github/login', async (ctx) => {
var dataStr = (new Date()).valueOf();
//重定向到认证接口,并配置参数
var path = "https://github.com/login/oauth/authorize";
path += '?client_id=' + config.client_id;
//转发到授权服务器
ctx.redirect(path);
})
router.get('/auth/github/callback', async (ctx) => {
console.log('callback..')
const code = ctx.query.code;
const params = {
client_id: config.client_id,
client_secret: config.client_secret,
code: code
}
let res = await axios.post('https://github.com/login/oauth/access_token', params)
const access_token = querystring.parse(res.data).access_token
res = await axios.get('https://api.github.com/user?access_token=' + access_token)
console.log('userAccess:', res.data)
ctx.body = `
<h1>Hello ${res.data.login}</h1>
<img src="${res.data.avatar_url}" alt=""/>
`
})
app.use(router.routes()); /*启动路由*/
app.use(router.allowedMethods());
app.listen(7001);
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<a href='/github/login'>login with github</a>
</div>
</body>
</html>
- sso 单点登录