说起鉴权大家应该都很熟悉, 不过作为前端开发来讲, 鉴权的流程大头都在后端小哥那边, 但是作为一个有志气的开发者肯定要好好学习整个鉴权流程以及方案, 不然怎么跟后端合作: smile:.
常见的鉴权方案
基于 Cookie, Session 认证
JWT 认证, Token 认证
OAuth2 认证
SSO 单点登陆
LDAP 认证登陆
扫码登陆
基于 Cookie, Session 认证
先上大家常见的一张 Cookie , Session 流程图.
例子展示
下面通过 node + koa + Redis 来展示上述的流程.
开发前准备
安装 node
安装 Redis 并且本地启动
note: 下面代码只是供 demo 展示, 具体代码结构设计在生产环境可不能这么写, 后面我会总结一篇关于 koa 最佳实践文章 .
启动 Redis
然后通过终端查看你的 Redis 有么有存储数据.
App.JS
- // App.JS
- const Koa = require("koa");
- const Router = require("koa-router");
- const bodyParser = require("koa-bodyparser");
- const session = require("koa-session2");
- const Store = require("./Store.js");
- const App = new Koa();
- const router = new Router();
- App.keys = ["this is my secret key"];
- App.use(bodyParser());
- App.use(
- session({
- key: "jssessionId"
- })
- );
- // 模拟登陆
- router.post("/login", async (ctx, next) => {
- const { username = "", password ="" } = ctx.request.body || {};
- // fake data
- const _username = "xyz";
- const _password = 123456;
- if (username === _username && password === _password) {
- const store = new Store();
- const sid = await store.set({
- username,
- password
- }, {
- maxAge: 1000 * 60 * 2 // 设定只有 120s 的有效时间
- });
- ctx.cookies.set('jssessionId', sid)
- ctx.body = {
- success: true,
- msg: "登陆成功"
- };
- } else {
- ctx.status = 401;
- ctx.body = {
- success: false,
- code: 10000,
- msg: "账号或者密码错误"
- };
- }
- });
- // 获取用户信息
- router.get(
- "/user",
- async (ctx, next) => {
- const store = new Store();
- const jssessionId = ctx.cookies.get('jssessionId')
- const userSession = await store.get(jssessionId)
- console.log('获取到请求的 cookie', jssessionId, 'session', userSession)
- if (!userSession) {
- ctx.status = 401;
- ctx.body = {
- success: false,
- msg: "oAuth Faill"
- };
- } else {
- ctx.userSession = userSession
- await next();
- }
- },
- async (ctx, next) => {
- ctx.body = {
- success: true,
- data: ctx.userSession
- };
- }
- );
- App.use(router.routes()).use(router.allowedMethods());
- App.on("error", (err, ctx) => {
- console.error("server error", err, ctx);
- });
- App.listen(3000, () => {
- console.log("Server listening on port 3000");
- });
Store.JS
- const Redis = require("ioredis");
- const { Store } = require("koa-session2");
- class RedisStore extends Store {
- constructor() {
- super();
- this.Redis = new Redis(); // Connect to 127.0.0.1:6379
- }
- async get(sid, ctx) {
- try {
- const data = await this.Redis.get(`jssessionId:${sid}`);
- return JSON.parse(data);
- } catch (err) {
- throw new Error(err);
- }
- }
- async set(session, { sid = this.getID(24), maxAge = 1000000 } = {}, ctx) {
- try {
- // EX: Redis 支持过了有效期自动删除
- await this.Redis.set(
- `jssessionId:${sid}`,
- JSON.stringify(session),
- "EX",
- maxAge / 1000
- );
- } catch (err) {
- throw new Error(err);
- }
- return sid;
- }
- }
- module.exports = RedisStore;
然后通过 postman 我们来测试下
注意看返回的 Set-Cookie, 接着我们看下 Redis
已经存在一条数据, 另外它的有效时间是 120S, 过了 120S 该数据会自动清除.
然后我们再通过另外接口去访问用户信息.
是可以获取到用户信息的, 说明一切正常.
120S 之后再次调用该接口测试是否已经失效.
Redis 里面也确实自动清除了该条数据.
备注
有错误的地方欢迎大家斧正, 源码地址.
最后有兴趣的关注一波公众号.
来源: http://www.tuicool.com/articles/F3AVvq6