Dart Shelf的认证和受权中间件html
提供Shelf中间件,用于验证用户(或系统)和创建会话,以及受权访问资源。java
注意:有关构建身份验证中间件的替代方法,请参阅下面的“身份验证生成器”部分。数据库
var authMiddleware = authenticate([ new BasicAuthenticator(new TestLookup()), new RandomAuthenticator()]));
Shelf Auth提供了一个authenicate函数,它接受一个Authenticators列表和一个可选的SessionHandler(见下文)并建立Shelf Middleware。安全
而后,您能够在shelf pipeline中的适当位置添加此Middleware.服务器
var handler = const Pipeline() .addMiddleware(exceptionHandler()) .addMiddleware(authMiddleware) .addHandler((Request request) => new Response.ok("I'm in with " "${getAuthenticatedContext(request).map((ac) => ac.principal.name)}\n")); io.serve(handler, 'localhost', 8080);
调用身份验证中间件时,它会按顺序经过身份验证器。 每一个Authenticator都执行如下操做之一cookie
第一个Authenticator返回成功身份验证或抛出异常。 若是Authenticator指示它未找到相关凭据,则调用列表中的下一个验证器。session
若是没有抛出异常,那么将调用传递给中间件的innerHandler。若是身份验证成功,则请求将在请求上下文中包含与身份验证相关的数据。这能够经过getAuthenticatedContext函数从当前请求中检索,也能够经过authenticatedContext从当前区域中检索。app
成功的认证会建立新区域(将通过身份验证的上下文设置为区域变量)。 可使用authenticatedContext函数访问它。dom
若是没有任何验证器处理请求,则调用innerHandler而不使用任何验证上下文。下游处理程序应该将其视为未经身份验证的(来宾)用户访问。您能够经过使用allowAnonymousAccess:false调用authenticate函数来拒绝匿名访问。ssh
若是没有为authenticate函数提供SesionHandler,则不会创建任何会话。 这意味着每一个请求都须要进行身份验证。 这适用于系统到系统调用以及基自己份验证等身份验证机制。
要在成功登陆时建立会话,还包括SessionHandler
var authMiddleware = authenticate([new RandomAuthenticator()], new JwtSessionHandler('super app', 'shhh secret', testLookup));
若是生成的AuthenticatedContext支持会话,则将在成功验证时调用SessionHandler。
请注意,除了指示身份验证是否成功以外,Authenticators还指示是否容许建立会话。对于某些认证机制(例如服务器到服务器调用),可能不但愿建立会话。
SessionHandlers提供了一个Authenticator,它始终是第一个为请求调用的身份验证器。只有在没有活动会话时才会调用其余身份验证器。
请注意,Shelf Auth不会涵盖session属性的存储(添加/检索)。这超出了范围。 只有会话处理的身份验证相关部分才在范围内。任何支持Shelf Auth标头或可与其集成的会话存储库均可以使用Shelf Auth。
Shelf Auth提供如下开箱即用的验证器:
支持基自己份验证(http://tools.ietf.org/html/rfc2617)
默认状况下,BasicAuthenticator不支持会话建立。 这能够在建立验证器时重写,以下所示
new BasicAuthenticator(new TestLookup(), sessionCreationAllowed: true)
用于专用登陆路由的Authenticator。 默认状况下,假定基于表单的POST使用名为username和password的表单字段,例如。
curl -i -H 'contentType: application/x-www-form-urlencoded' -X POST -d 'username=fred&password=blah' http://localhost:8080/login
这种身份验证方式几乎老是与创建会话相关联。
var loginMiddleware = authenticate( [new UsernamePasswordAuthenticator(lookupByUsernamePassword)], sessionHandler: sessionHandler);
您能够设置登陆路由(在此示例中使用shelf_route)并传入此中间件。
rootRouter.post('/login', (Request request) => new Response.ok( "I'm now logged in as ${loggedInUsername(request)}\n"), middleware: loginMiddleware);
如今,您一般会设置经过登陆时创建的会话访问的其余路由。
var defaultAuthMiddleware = authenticate([], sessionHandler: sessionHandler, allowHttp: true, allowAnonymousAccess: false); rootRouter.child('/authenticated', middleware: defaultAuthMiddleware) ..get('/foo', (Request request) => new Response.ok( "Doing foo as ${loggedInUsername(request)}\n"));
在此示例中,以/ authenticated开头的全部路由都须要有效的会话。
认证人员名单预计会随着时间的推移而增加。
此外,您能够轻松建立本身的自定义身份验证器。
Shelf Auth提供如下开箱即用的SessionHandler:
这使用JWT建立在响应的Authorization标头中返回的身份验证令牌。后续请求必须在Authorization标头中传回令牌。这是一种承载风格的令牌机制。注意:与HTTP消息中传递的全部安全凭证同样,若是有人可以拦截请求或响应,则他们能够窃取令牌并模拟用户。确保使用HTTPS。
特征
其余会话处理程序(如基于cookie的机制)可能会在将来添加
为了简化建立身份验证中间件的过程,特别是在使用捆绑的身份验证器和会话处理程序时,会提供构建器。例如
var authMiddleware = (builder() .basic(userNamePasswordLookup, sessionCreationAllowed: true) .jwtSession('me', 'sshh', usernameLookup) ..allowHttp=true) .build();
注意:此示例有点复杂,由于您一般不但愿使用基自己份验证建立会话
var authorisationMiddleware = authorise([new SameOriginAuthoriser()]);
Shelf Auth提供authorise函数,该功能获取Authoriser列表并建立Shelf Middleware。
此外,authorisationBuilder还提供了一个用于建立受权中间件的构建器,包括开箱即用的受权者
var authorisationMiddleware = (authorisationBuilder() .sameOrigin() .principalWhitelist((Principal p) => p.name == 'fred')) .build();
若是任何受权人(Authoriser)拒绝访问,则:
Shelf Auth提供如下受权商:
仅容许访问通过身份验证的用户。 若是请求中没有当前的AuthenticatedContext,则拒绝访问。
经过拒绝访问引用不是来自与请求URL相同的主机的请求来帮助防止XSRF攻击。
容许访问做为给定PrincipalWhiteList一部分的任何主体的受权者。
PrincipalWhiteList能够以多种方式实现。 例如,它根据名称中的静态内存列表检查主体名称。
final whitelist = [ 'fredlintstone@stone.age' ]; final whitelistAuthoriser = new PrincipalWhitelistAuthoriser( (Principal p) => whitelist.contains(p.name));
或者它可能会针对数据库检查用户组。