Vert.x附带一些用于处理认证和授权的开箱即用的处理程序。
创建一个Auth处理程序
router.route().handler(CookieHandler.create()); router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx))); AuthHandler basicAuthHandler = BasicAuthHandler.create(authProvider);
在您的应用程序中处理auth
对以/private开头的路径授权。
router.route().handler(CookieHandler.create()); router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx))); router.route().handler(UserSessionHandler.create(authProvider)); AuthHandler basicAuthHandler = BasicAuthHandler.create(authProvider); // All requests to paths starting with '/private/' will be protected router.route("/private/*").handler(basicAuthHandler); router.route("/someotherpath").handler(routingContext -> { // This will be public access - no login required }); router.route("/private/somepath").handler(routingContext -> { // This will require a login // This will have the value true boolean isAuthenticated = routingContext.user() != null; });
HTTP基本认证
如果访问需要授权的资源,会返回401的响应,提示用户登录。
重定向认证处理程序
如果用户没登录,会被定向到登录页面。
示例:
router.route().handler(CookieHandler.create()); router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx))); router.route().handler(UserSessionHandler.create(authProvider)); AuthHandler redirectAuthHandler = RedirectAuthHandler.create(authProvider); // All requests to paths starting with '/private/' will be protected router.route("/private/*").handler(redirectAuthHandler); // Handle the actual login // One of your pages must POST form login data router.post("/login").handler(FormLoginHandler.create(authProvider)); // Set a static server to serve static resources, e.g. the login page router.route().handler(StaticHandler.create()); router.route("/someotherpath").handler(routingContext -> { // This will be public access - no login required }); router.route("/private/somepath").handler(routingContext -> { // This will require a login // This will have the value true boolean isAuthenticated = routingContext.user() != null; });
JWT授权
没有权限的用户将被拒绝访问。
- 发送令牌
- 过滤请求
这种方式只能用HTTPS,不然会出现会话劫持攻击。
发送令牌示例
Router router = Router.router(vertx); JsonObject authConfig = new JsonObject().put("keyStore", new JsonObject() .put("type", "jceks") .put("path", "keystore.jceks") .put("password", "secret")); JWTAuth authProvider = JWTAuth.create(vertx, authConfig); router.route("/login").handler(ctx -> { // this is an example, authentication should be done with another provider... if ("paulo".equals(ctx.request().getParam("username")) && "secret".equals(ctx.request().getParam("password"))) { ctx.response().end(authProvider.generateToken(new JsonObject().put("sub", "paulo"), new JWTOptions())); } else { ctx.fail(401); } });
使用令牌
Router router = Router.router(vertx); JsonObject authConfig = new JsonObject().put("keyStore", new JsonObject() .put("type", "jceks") .put("path", "keystore.jceks") .put("password", "secret")); JWTAuth authProvider = JWTAuth.create(vertx, authConfig); router.route("/protected/*").handler(JWTAuthHandler.create(authProvider)); router.route("/protected/somepage").handler(ctx -> { // some handle code... });JWT可以添加你需要的信息,服务器不存储状态,你将不需要集群会话。
JsonObject authConfig = new JsonObject().put("keyStore", new JsonObject() .put("type", "jceks") .put("path", "keystore.jceks") .put("password", "secret")); JWTAuth authProvider = JWTAuth.create(vertx, authConfig); authProvider.generateToken(new JsonObject().put("sub", "paulo").put("someKey", "some value"), new JWTOptions());
获取添加的信息
Handler<RoutingContext> handler = rc -> { String theSubject = rc.user().principal().getString("sub"); String someKey = rc.user().principal().getString("someKey"); };
配置需要的权限
例如
AuthHandler listProductsAuthHandler = RedirectAuthHandler.create(authProvider); listProductsAuthHandler.addAuthority("list_products"); // Need "list_products" authority to list products router.route("/listproducts/*").handler(listProductsAuthHandler); AuthHandler settingsAuthHandler = RedirectAuthHandler.create(authProvider); settingsAuthHandler.addAuthority("role:admin"); // Only "admin" has access to /private/settings router.route("/private/settings/*").handler(settingsAuthHandler);
链接多个auth处理程序
知道某些处理程序需要特定的提供程序非常重要,例如:
因此,预计供应商将不会在所有处理程序中共享。有些情况下可以在处理程序中共享提供程序,例如:
该
BasicAuthHandler
可以采取任何提供商。该
RedirectAuthHandler
可以采取任何提供商。
所以说,你要创建一个接受两个应用程序HTTP Basic Authentication
和Form Redirect
。你会开始配置你的链:
ChainAuthHandler chain = ChainAuthHandler.create(); // add http basic auth handler to the chain chain.append(BasicAuthHandler.create(provider)); // add form redirect auth handler to the chain chain.append(RedirectAuthHandler.create(provider)); // secure your route router.route("/secure/resource").handler(chain); // your app router.route("/secure/resource").handler(ctx -> { // do something... });
因此,当用户发出没有Authorization
标头的请求时,这意味着链将无法通过基本身份验证处理程序进行身份验证,并尝试使用重定向处理程序进行身份验证。由于重定向处理程序总是重定向,因此您将被发送到您在该处理程序中配置的登录表单。
与vertx-web中的正常路由一样,auth chaning是一个序列,因此如果您希望回退到您的浏览器,并使用HTTP基本身份验证请求用户凭据而不是重定向,则需要的所有操作都是反向追加到连锁,链条。
现在假设您在提供Authorization
值的标题处发出请求Basic [token]
。在这种情况下,基本身份验证处理程序将尝试进行身份验证,如果成功,则链将停止并且vertx-web将继续处理您的处理程序。如果令牌无效,例如错误的用户名/密码,则该链接将继续到以下条目。在这个特定情况下,重定向认证处理程序。