颤抖的Web Cookie /令牌会话和身份验证

时间:2019-08-20 15:33:54

标签: session cookies flutter dart token

我正在使用 NodeJS和Flutter For Web 开发一个全栈应用程序,此刻,我不知道如何进行安全的cookie /令牌会话。 br /> 我需要的答案是如何使用Flutter For Web构建身份验证系统,就像其他社交网络或Stackoverflow本身一样。

2 个答案:

答案 0 :(得分:4)

Flutter 1.9不支持直接导入dart.htmlReference

我在寻找解决方案的过程中遇到了universal_html软件包,它对我来说很好用。以下是我的帮助程序类,用于在网络上本地存储键值对:

import 'package:universal_html/prefer_universal/html.dart';

class WebStorage {

  //Singleton
  WebStorage._internal();
  static final WebStorage instance = WebStorage._internal();
  factory WebStorage() {
    return instance;
  }

  String get sessionId => window.localStorage['SessionId'];
  set sessionId(String sid) => (sid == null) ? window.localStorage.remove('SessionId') : window.localStorage['SessionId'] = sid;
}

要阅读,

  

WebStorage.instance.sessionId;

要写

  

WebStorage.instance.sessionId ='YOUR_CREDENTIAL';

示例:

fetchPost(params, "CMD_USERREGISTRATION").then((result) {
        ...
        APIResponse response = APIResponse(xmlString: result.body);

        if (!response.isSuccess()) {
          ...
          return;
        }
        var sid = response.getSessionId();

        if (kIsWeb) {
          WebStorage.instance.sessionId = sid;
        }
}

main.dart:

@override
  Widget build(BuildContext context) {
    if (kIsWeb) {
      isLogin = WebStorage.instance.sessionId != null;
    } else {
      isLogin = //check from SharedPreferences;
    }
    return isLogin ? dashboardPage() : loginPage();
  }

答案 1 :(得分:4)

这是一个老问题,但所选择的答案并不完全安全。 对于网络而言,将网络存储用于敏感信息并不安全。

您应该使用仅限 http 的 cookie。无法通过 Javascript 读取 Http-only cookie,但浏览器会自动将其发送到后端。

这是 Nodejs-Express-TypeScript 代码示例;

在这个例子中,有两个 cookie,一个是 http-only,另一个不是。 non-http-only cookie 用于检查登录情况,如果它是有效的客户端假定用户已登录。但实际控制由后端完成。

PS:不需要存储或发送任何令牌,因为浏览器会自动处理它(cookies)。

const cookieConfig = {
  httpOnly: true,
  secure,
  maxAge: 30 * 24 * 60 * 60 * 1000,
  signed: secure,
}

const cookieConfigReadable = {
  httpOnly: false,
  secure,
  maxAge: 30 * 24 * 60 * 60 * 1000,
  signed: secure,
}

function signToken(unsignedToken: any) {
  const token = jwt.sign(unsignedToken, privatekey, {
    algorithm: 'HS256',
    expiresIn: jwtExpirySeconds,
  })

  return token
}

const tokenObj = {
  UID: userId,
  SID: sessionId,
}

const token = signToken(tokenObj)

// sets session info to the http-only cookie
res.cookie('HSINF', token, cookieConfig) 

// sets a cookie with expires=false value for client side check.
res.cookie('expired', false, cookieConfigReadable) 

但是这种方法在调试过程中存在一个挑战,因为 NodeJS 和 Flutter Web 服务在不同的端口上,你应该允许开发环境的 CORS。

if (process.env.NODE_ENV === 'dev') {
  app.use(
    cors({
      origin: [
        'http://localhost:8080',
        'http://127.0.0.1:8080',
      ],
      credentials: true,
    }),
  )
}

并且在 Flutter Web 中,您不能在调试期间直接使用 http.get 或 http.post,因为 Flutter 默认禁用 CORS cookie。

这里有一个解决方法。

// withCredentials = true is the magic
var client = BrowserClient()..withCredentials = true;
http.Response response;
try {
  response = await client.get(
    Uri.parse(url),
    headers: allHeaders,
  );
} finally {
  client.close();
}

在调试中还有另一个挑战;许多浏览器不允许 localhost 使用 cookie,您应该使用 127.0.0.1 代替。但是 Flutter Web 只针对特定的 url 和特定的端口运行,所以这是我的 Flutter 在 127.0.0.1 上运行的 VsCode 配置

 {
      "name": "project",
      "request": "launch",
      "type": "dart",
      "program": "lib/main.dart",
      "args": [
        "-d",
        "chrome",
        "--web-port",
        "8080",
        "--web-hostname",
        "127.0.0.1"
      ]
    }

这些是用来设置和传输cookie的,下面你可以找到我的后端cookie检查

const httpOnlyCookie = req.signedCookies.HSINF
const normalCookie = req.signedCookies.expired

if (httpOnlyCookie && normalCookie === 'false') {
  token = httpOnlyCookie
}

if (token) {
  let decoded: any = null
  try {
    decoded = jwt.verify(token, privatekey)
  } catch (ex) {
    Logger.error(null, ex.message)
  }

  if (decoded) {
    //Cookie is valid, get user with the session id
  }
}