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将继续处理您的处理程序。如果令牌无效,例如错误的用户名/密码,则该链接将继续到以下条目。在这个特定情况下,重定向认证处理程序。