Koa (2) of the - authentication (Cookie / Session, Token, and the OAuth)

  Previously unseparated front and rear ends, the page is rendered by the background, you can directly access to the page is determined by the background logic. After separation of the front and rear ends, a page element is controlled by the page itself, the routing between pages controlled by the front end. Of course, only the front-end access control to do is not enough, still needs to be done to verify the background for each interface.
  Why do front-end access control is not enough of it? Because the route is only the tip of the control of visual control, front-end can hide a page or a button, send the request but there are still many, you can skip the operation page to send a request. So even if the front of the control authority to do very tight, the background still need to verify that each interface.
  The front end of the control rights are mainly three: the routing control (routing jump), the control view (buttons level) and the control request (request interceptor). After this in several ways and then go into the details, the front finish access control, still need to verify the background of each interface, which is authentication. Now with the front and rear end authentication methods are mainly the following:

  1. session-cookie
  2. Token authentication (the JWT)
  3. OAuth (Open Authorization)

session-cookie

cookie

  Http protocol is a stateless protocol, the server does not know in the end Which browser to access it, and therefore requires an identity for the server to distinguish between different browsers. cookie that identifies the state between the management server and the client.
  cookie principle is that the first time the server sends a request to the browser, the server sets Set-Cookie header field in response, the browser receives the response and stores the cookie will be set, the next time the browser sends a request to the server, will automatically bring the cookie field in the request header, the server receives the cookie is used to distinguish between different browsers. Of course, this cookie correspondence between a user and the server should be there at the first visit, then you need a session.

const http = require('http')
http.createServer((req, res) => {
  if (req.url === '/favicon.ico') {
    return
  } else {
    res.setHeader('Set-Cookie', 'name=zhunny')
    res.end('Hello Cookie')
  }
}).listen(3000) 
复制代码

session

  session is a session means the browser's first visit to the server, the server will create a session, save information that identifies the browser in the session. It differs from the cookie is session is cached on the server side, the cookie is cached on the client, the server generated by them, in order to make up for the stateless Http protocol defects.

session-cookie authentication

  1. In an interview with the server creates a client's first visit to seesion on the server side, and then save seesion (seesion we can be saved in memory, can also be stored in redis, it is recommended to use the latter), then this session to generate a unique identification character string, then this kind of unique identification string in the response header.
  2. signature. This step keys on sid signing process by avoiding client modifies sid. (Non-essential step)
  3. When a browser receives a request response will parse the response headers, and then save sid in a local cookie, browser request header next http request will bring the cookie information in this domain.
  4. In an interview with the server requests the client to parse the request header in the cookie sid, and then go to the client's session stored on the server side based on this sid, and then determine whether the request is legitimate.
const http = require('http')
//此时session存在内存中
const session = {}
http.createServer((req, res) => {
  const sessionKey = 'sid'
  if (req.url === '/favicon.ico') {
    return
  } else {
    const cookie = req.headers.cookie
    //再次访问,对sid请求进行认证
    if (cookie && cookie.indexOf(sessionKey) > -1) {
      res.end('Come Back')
    }
    //首次访问,生成sid,保存在服务器端
    else {
      const sid = (Math.random() * 9999999).toFixed()
      res.setHeader('Set-Cookie', `${sessionKey}=${sid}`)
      session[sid] = { name: 'zhunny' }
      res.end('Hello Cookie')
    }
  }
}).listen(3000)
复制代码

repeat

  redis is a key server, you can put a special session of the key pair. How to use the session in koa in:

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')
const client = wrapper(redisClient)

//加密sessionid
app.keys = ['session secret']

const SESS_CONFIG = {
  key: 'kbb:sess',
  //此时让session存储在redis中
  store: redisStore({ client })
}

app.use(session(SESS_CONFIG, app))

app.use(ctx => {
  //查看redis中的内容
  redisClient.keys('*', (errr, 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)
复制代码

User login authentication

  When using session-cookie do login authentication, logon storage session, deleted Log session, while the other interfaces need to be logged in to the needs of the operation in advance to verify the existence of session, there is a jump to the page, then back to the login page does not exist .
  Do a verification koa in the middleware using the middleware interfaces that require authentication.

//前端代码
async login() {
    await axios.post('/login', {
        username: this.username,
        password: this.password
    })
},
async logout() {
    await axios.post('/logout')
},
async getUser() {
    await axios.get('/getUser')
}
复制代码
//中间件 auth.js
module.exports = async (ctx, next) => {
  if (!ctx.session.userinfo) {
    ctx.body = {
      ok: 0,
      message: "用户未登录" };
  } else {
    await next();
} };
//需要验证的接口
router.get('/getUser', require('auth'), async (ctx) => {
  ctx.body = {
    message: "获取数据成功",
    userinfo: ctx.session.userinfo
  }
})
//登录
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: "登出系统"
  }
})
复制代码

Token

  token is a token, a token will be issued when the first browser to access the server, the browser after each carries this token to access the server will authenticate the token is valid, as long as the server can decrypt the token, it shows the request is legitimate, the user information contained in the token may also distinguish between different user identities. Generally token consists of user information, time stamp and signature encrypted by hash algorithm.

Token certification process

  1. The client uses the user login name with the password request
  2. Server receives a request to verify the user name and password
  3. After successful authentication, the server will issue a Token, then the Token is sent to the client
  4. After receiving the client Token it can be stored, such as on the inside or Local Storage in Cookie
  5. Every time a client requests a resource to the server needs with the server issued Token
  6. Token (request to add the Authorization header) server receives the request, then the client request to verify with the inside, if the verification is successful, it returns the requested data to the client terminal 401 returns an error code if unsuccessful, the authentication fails.

Token session and the difference

  1. The disadvantage of session-cookie: (1) limited the use of authentication in a browser, cookie is a mechanism for the browser, and if you can not use the app end cookie. (2) In order to meet global consistency, we'd better be stored in redis session persistence to do, but in a distributed environment, we may need to back up on each server, taking up a lot of storage space. (3) the use of cookie in Https agreement is not vulnerable to CSRF cross-site request forgery attacks.
  2. Token disadvantages: (1) consumption of such cryptographic authentication token consumption performance more than the session-cookie. (2) token than sessionId large, accounted for more bandwidth.
  3. Comparison between the two, the difference between them is obvious: (1) token authentication is not limited to the cookie, so that makes this authentication method can support multiple clients, not just a browser. And it is not affected by the same origin policy. (2) do not use cookie can circumvent CSRF attacks. (. 3) need not be stored token, the token is included in the user information, into a stateless server, the server only needs to verify the legitimate token on the list according to the rules defined. It also makes scalability token stronger.

JWT(JSON Web Token)

  JWT principle is, after authentication server generates a JSON object, and this certainly can not bare JSON object passed to the user, and that no one can tamper with this object sends a request. So the JSON object will be returned to the user server-side signature encryption, content is the return of a token, after the user each time you access the server on with this token.
  The JSON object may contain content that is expired time user information, user identity and token.

Part of JWT

  The site in the JWT , can decode or encode a JWT. A JWT form:


  It consists of three parts: Header (head), Payload (load), Signature (signature).

  1. Header section is a JSON object, metadata that describes the JWT. Information for the encryption algorithm and a type of Token Token general description. {"alg": "HS256","typ": "JWT"}Which means that the HS256 use encryption token, token type is JWT. This corresponds to the basic portion of the plaintext, it will do this a JSON object Base64 transcoding into a string. Is Base64 encoding decoding algorithm, the decoding process is reversible. The default header information carries two fields.
  2. Payload is part of a JSON object, used to store the actual data transfer is required. There are seven official fields, you can also define a private field in this section. General store user name, user identity and some JWT description field. It is also just did a Base64 encoded, and therefore can not be sure which store secret information, such as login password and the like.
  3. Signature signature on the front portion of the two, to prevent tampering with the data, if the foregoing two pieces of information is sent to the server a modified human, are available at this time server signature to verify the accuracy of the information. Signature requires a key, the key is stored on the server side, users do not know. After calculating the signature, the Header, Payload, Signature makes up a string of three parts, (.) Separated by a "point" between each section can be returned to the user.
JWT features
  1. JWT default are not encrypted, but also can be encrypted. After generating the original Token, it can be re-encrypted with a key once.
  2. JWT case without encryption, secret data can not be written to JWT.
  3. JWT not only can be used for authentication, it can also be used to exchange information. Effective use of JWT, the number of server queries the database can be reduced.
  4. JWT biggest drawback is that, because the server does not save session state, a token can not be abolished in the course of, or change the permissions of the token. That is, once issued JWT, will remain in effect until maturity, unless the server to deploy additional logic.
  5. JWT itself contains authentication information, when disclosed, anyone can get all the permissions of the token. To reduce theft, JWT's validity should be set relatively short. For some of the more important rights, should once again to authenticate the user during use.
  6. To reduce theft, JWT should not use the HTTP protocol transmission codes, to use the HTTPS protocol.
JWT authenticate user logins
//前端代码
//axios的请求拦截器,在每个request请求头上加JWT认证信息
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);
    }
);
//登录方法:在将后端返回的JWT存入localStorage
async login() {
    const res = await axios.post("/login-token", {
        username: this.username,
        password: this.password
    });
    localStorage.setItem("token", res.data.token);
},
//登出方法:删除JWT
async logout() {
    localStorage.removeItem("token");
},
async getUser() {
    await axios.get("/getUser-token");
}
复制代码
//后端代码
const jwt = require("jsonwebtoken");
const jwtAuth = require("koa-jwt");
//用来签名的密钥
const secret = "it's a secret";

router.post("/login-token", async ctx => {
  const { body } = ctx.request;
  //登录逻辑,略,即查找数据库,若该用户和密码合法,即将其信息生成一个JWT令牌传给用户
  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
    )
  };
});

//jwtAuth这个中间件会拿着密钥解析JWT是否合法。
//并且把JWT中的payload的信息解析后放到state中,ctx.state用于中间件的传值。
router.get(
  "/getUser-token",
  jwtAuth({
    secret
  }),
  async ctx => {
    // 验证通过,state.user
    console.log(ctx.state.user);
    ctx.body = {
      message: "获取数据成功",
      userinfo: ctx.state.user.data 
    };
  }
)
//这种密码学的方式使得token不需要存储,只要服务端能拿着密钥解析出用户信息,就说明该用户是合法的。
//若要更进一步的权限验证,需要判断解析出的用户身份是管理员还是普通用户。
复制代码

OAuth

  Login tripartite mainly based on OAuth 2.0. OAuth protocol provides a secure authorized user resources, open but simple standard. With the previous authorization way except that the third-party OAuth authorization will not touch the account information (such as user name and password), that a third party without the use of user name and password that the user can apply for resources Authorizations, OAuth is safe. We provide common OAuth authentication service firms Alipay, QQ, micro letter. This License allows users to use low threshold, they can better promote their application.
  OAuth Related Articles Ruan Yifeng teacher recommended a series of articles OAuth 2.0 .

OAuth authentication process

  OAuth is a kind of authorization mechanisms. Tell the owner of the data system, agreed to authorize third-party applications into the system, access to these data. System to produce a short-term entry token (token), is used instead of the password for using third party applications.
  OAuth There are four ways to get a token, no matter what kind of License, third-party applications to apply before the token must first come first filing system, identify themselves, and then will get two identification code: Client ID (client ID) and a client secret (client secret). This is to prevent abuse of the token, had no record of third-party applications will not get the token.
  The rear end of the front separation context, we often use the authorization code mode, a third-party application means to apply for an authorization code, and then use the acquired token code.

Sign in GitHub example

  We use an example to clarify the way the authorization code process.

  1. GitHub record in the third-party application, get it belongs to the client ID and client secret.

  Create an OAuth App on github-settings-developer settings in. And fill in the relevant content. Filling is completed Github will give you a client ID and a client secret.


2. At this point in your third-party sites can provide a Github login link, the user clicks on the link will jump to Github. This step took the client ID code request an authorization code to Github.

const config = {
  client_id: '28926186082164bbea8f',
  client_secret: '07c4fdae1d5ca458dae3345b6d77a0add5a785ca'
}

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);
})
复制代码
  1. Jump to Github user, enter your user name and password Github, the user agrees to log in to third party websites using Github identity. At this time, with the authorization code code will jump back to third-party websites. Jump back to address when creating the OAuth been set up.http://localhost:3000/github/callback
  2. Third-party sites received authorization code, you can hold the authorization code, the client ID and client secret whereabouts Github access_token request token.
  3. Github receipt of the request, issues tokens to third-party websites.
  4. After a third-party site receives a token, you can temporarily have permission Github some requests, such users to get information, to get this information users can build their own third-party websites token, do the relevant authentication operation.
router.get('/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=""/>
    `

})
复制代码

reference

cookie, session silly you could not tell?
The cookie talked clear
end common types of authentication way around
the front end of the interview you may say - (X) front-end authentication
talk about front-end permissions
OAuth 2.0 in four ways

Reproduced in: https: //juejin.im/post/5cdb83fe51882569223af7ae

Guess you like

Origin blog.csdn.net/weixin_33722405/article/details/93179552