Flutter会话管理插件session_shelf的使用
Flutter会话管理插件session_shelf的使用
session_shelf
是 shelf
框架的一个实现,用于通过文件或SQL数据库存储会话信息。该插件基于 mezoni
的 shelf_session
,具有更强大的功能。
关于
session_shelf
添加了两个中间件给 shelf
:
cookiesMiddleware
sessionMiddleware
cookiesMiddleware
可以独立使用。
sessionMiddleware
依赖于 cookiesMiddleware
并必须在其之后使用。
final pipeline = const Pipeline()
.addMiddleware(cookiesMiddleware())
.addMiddleware(sessionMiddleware())
.addHandler(handler);
示例代码
以下是一个简单的可运行示例:
import 'dart:io' show Cookie;
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_router/shelf_router.dart';
import 'package:session_shelf/session_shelf.dart';
import 'package:shelf_static/shelf_static.dart';
void main(List<String> args) async {
final router = Router();
router.get('/', _handleHome);
router.get('/login', _handleLogin);
router.get('/login/', _handleLogin);
router.post('/login', _handleLogin);
router.post('/login/', _handleLogin);
router.get('/logout', _handleLogout);
router.get('/logout/', _handleLogout);
final staticHandler = createStaticHandler('web', defaultDocument: 'index.html');
final handler = Cascade().add(staticHandler).add(router).handler;
final pipeline = const Pipeline()
.addMiddleware(logRequests())
.addMiddleware(cookiesMiddleware())
.addMiddleware(sessionMiddleware())
.addHandler(handler);
const address = 'localhost';
const port = 8080;
final server = await io.serve(pipeline, address, port);
print('Serving at http://${server.address.host}:${server.port}');
}
const _menu = '''
<a href="/">Home</a><br />
<a href="/login">Log in</a><br />
<a href="/logout">Log out</a><br />''';
Future<Response> _handleHome(Request request) async {
final userManager = UserManager();
final user = await userManager.getUser(request);
var body = '$_menu{{message}}<br />{{cookies}}';
if (user == null) {
body = body.replaceAll('{{message}}', 'You are not logged in');
} else {
body = body.replaceAll('{{message}}', 'You are logged in as ${user.name}');
}
final cookies = request.getCookies();
body = body.replaceAll('{{cookies}}',
cookies.entries.map((e) => '${e.key}: ${e.value}').join('<br />'));
request.addCookie(Cookie('foo', 'Foo'));
if (!cookies.containsKey('baz')) {
request.addCookie(Cookie('baz', 'Baz'));
} else {
request.removeCookie(Cookie('baz', ''));
}
return _render(body);
}
Future<Response> _handleLogin(Request request) async {
const html = '''
<form action="" method="post">
<label>Login</label><br />
<input name="login" type="text" /><br />
<label>Password</label><br />
<input name="password" type="password" /><br /><br />
<button>Log in</button>
</form>
''';
if (request.method == 'GET') {
return _render(_menu + html);
}
final body = await request.readAsString();
final queryParameters = Uri(query: body).queryParameters;
final login = queryParameters['login'] ?? ''
..trim();
final password = queryParameters['password'] ?? ''
..trim();
if (login.isEmpty || password.isEmpty) {
return _render(_menu + html);
}
final user = User(login);
final userManager = UserManager();
await userManager.setUser(request, user);
return Response.found('/');
}
Future<Response> _handleLogout(Request request) async {
await Session.deleteSession(request);
return Response.found('/');
}
Response _render(String body) {
return Response.ok(body, headers: {
'Content-type': 'text/html; charset=UTF-8',
});
}
class User {
final String name;
User(this.name);
}
class UserManager {
Future<User?> getUser(Request request) async {
final session = await Session.getSession(request);
if (session == null) {
return null;
}
final user = session.data['user'];
if (user is User) {
return user;
}
return null;
}
Future<User> setUser(Request request, User user) async {
var session = await Session.getSession(request);
session ??= await Session.createSession(request);
session.data['user'] = user;
return user;
}
}
存储会话数据
默认情况下,会话数据存储在运行时的哈希映射中。这表示会话数据只应为授权用户创建。这种方法可以防止各种类型的攻击导致内存溢出。会话数据在过期后会自动删除(这会导致内存被释放)。定时器不用于这些目的,而是发生在新会话创建时。
文件存储
要将会话数据存储在文件中,请使用 FileStorage.plain
:
main() {
Session.storage = FileStorage.plain(Directory('session_shelf'));
}
加密文件存储
要将加密的会话数据存储在文件中,请使用 FileStorage.crypto
:
main() {
Session.storage = FileStorage.crypto(Directory('session_shelf'), algorithm, secretKey);
}
SQL数据库存储
要将会话数据存储在SQL数据库中,请使用 SqlStorage
:
final db = sqlite3.openInMemory();
main() async {
Session.storage = SqlStorage('session_shelf', db.execute, (sql) {
final ResultSet resultSet = db.select(sql);
return resultSet;
});
await Session.storage.createTable();
}
加密SQL数据库存储
要将加密的会话数据存储在SQL数据库中,请使用 SqlCryptoStorage
:
final db = sqlite3.openInMemory();
main() async {
Session.storage = SqlCryptoStorage('session_shelf_crypto', db.execute, (sql) {
final ResultSet resultSet = db.select(sql);
return resultSet;
// 这只是一个示例。请勿在代码中写入您的密钥。
}, algorithm, secretKey);
await Session.storage.createTable();
}
处理复杂类型的数据
如果您的数据包含非基本类型,可以设置自定义序列化方法:
void setupJsonSerializer() {
Session.toEncodable = (obj) {
if (obj is User) {
return {
'type': 'User',
'name': obj.name,
};
}
return obj;
};
Session.reviver = (k, v) {
if (v is Map && v.length == 2 && v['type'] == 'User' && v.containsKey('name')) {
return User(v['name'] as String);
}
return v;
};
}
更多关于Flutter会话管理插件session_shelf的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复