Sessions in dart

2019-03-19 23:12发布

问题:

Usually the dart documentation has a lot of useful examples on almost any topic. Unfortunately I could not find anything on sessions in dart.

Could anyone validate this approach as a correct way to do sessions:

  1. Browser sends GET request to sever.
  2. Server responds with web-client.
  3. Web-client sends user credentials.
  4. a) Server checks credentials and generates session cookie. b) Server sends session cookie back to client.
  5. Web-client stores cookie for further use.
  6. Web-client sends request for some user specific data, and attaches the cookie for verification.

My special interest lies in points 4, 5 and 6, since the others are well documented. If you could share some code snippets on this points, I would very much appreciate it.

EDIT: After reading the comment from Günter Zöchbauer below I looked into shelf_auth. I realized that it requires rewriting the server app to use shelf. So I did that.

The main.dart:

// imports of all necessary libraries

main() {
    runServer();
}


/**
 *  Code to handle Http Requests
 */
runServer() {
  var staticHandler = createStaticHandler(r"C:\Users\Lukasz\dart\auctionProject\web", defaultDocument: 'auctionproject.html');
  var handler = new Cascade()
                      .add(staticHandler)  // serves web-client
                      .add(routes.handler) // serves content requested by web-client
                      .handler;
  io.serve(handler, InternetAddress.LOOPBACK_IP_V4, 8080).then((server) {
    print('Listening on port 8080');
  }).catchError((error) => print(error)); 
}

The routes.dart

import 'handlers.dart' as handler;

import 'package:shelf_route/shelf_route.dart';
import 'package:shelf_auth/shelf_auth.dart' as sAuth;

Router routes = new Router()
         ..get('/anonymous', handler.handleAnonymousRequest);
         //..post('/login', handler.handleLoginRequest); << this needs to be implemented
                      //other routs will come later

The handlers.dart

import 'dart:async';
import 'dart:convert';
import 'dart:io' show HttpHeaders;    
import 'databaseUtility.dart';
import 'package:shelf_exception_response/exception.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf_path/shelf_path.dart';


shelf.Response handleAnonymousRequest(shelf.Request request) {
  return new shelf.Response.ok('got anonymous get request');
}

Unfortunately after reading the shelf_auth documentation I still don't quite know where to add the authentication. They use the Pipline syntax for the handler.

回答1:

I'll describe how session works in Java with servlets. This could help you in making your implementation work. First off, I have to mention that session and authentication are two separate functions, although the latter depends on the former.

A session helps the server understand consecutive requests coming from the same browser without a big idle time in between. Take a look at the below example:

  1. A user opened a browser A, visited your site
  2. Kept clicking around various links using multiple tabs in browser A
  3. Left the browser idle for 45 minutes
  4. Continued clicking on the pages that he left open
  5. Opened browser B, visited your site
  6. Closed the tab for your website in browser B
  7. Opened another new tab in browser B and clicked on a bookmark to visit your site

Here is the impact on the server-side session for the above steps of the user:

  1. New session created... let us say JSESSIONID 10203940595940
  2. Same session applies for all requests from all tabs
  3. Session expired on the server, and probably some memory was freed on server
  4. Since Java is not able to locate a session matching JSESSIONID 10203940595940, it creates a new session and asks client to remember new JSESSIONID w349374598457
  5. Requests from new browser are treated as new sessions because the JSESSIONID contract is between a single browser and the server. So, server assigns a new JSESSIONID like 956879874358734
  6. JSESSIONID hangs around in the browser till browser is exited. Closing a tab doesnt clear the JSESSIONID
  7. JSESSIONID is still used by browser, and if not much time elapsed, server would still be hanging on to that session. So, the sesison will continue.

Session use on the server-side:

  • A session is just a HashMap which maps JSESSIONIDs with another a bunch of attributes.
  • There is a thread monitoring elapsed time for the sessions, and removing JSESSIONIDs and the mapped attributes from memory once a session expires.
  • Usually, there is some provision for applications to get an event alert just when a session becomes ready for expiry.

Implementation details:

  • User's browser A sends a request to server. Server checks if there is a Cookie by name JSESSIONID. If none is found, one is created on the server. The server makes a note of the new JSESSIONID, the created time, and the last request time which is the same as created time in this case. In the HTTP response, the server attaches the new JSESSIONID as a cookie.
  • Browsers are designed to keep attaching cookies for subsequent visits to the same site. So, for all subsequent visits to the site, the browser keeps attaching the JSESSIONID cookie to the HTTP request header.
  • So, this time the server sees the JSESSIONID and is able to map the request to the existing session, in case the session has not yet expired. In case the session had already expired, the server would create a new session and attach back the new JSESSIONID as a cookie in HTTP response.

Authentication mechanisms just make use of the above session handling to detect "new sessions" and divert them to the login page. Also, existing sessions could be used to store attributes such as "auth-status" - "pass" or "fail".