Vert.x JWT 授权禁止访问
Vert.x JWT auth gives Forbidden access
场景
我在我的 HTTP 服务器 Verticle 的 start()
中调用此方法:
private void setupAuth(Router router) {
// Secure access key
var config = new JWTAuthOptions()
.setKeyStore(new KeyStoreOptions()
.setType("jceks")
.setPath("C:\Users\3587741\Desktop\Projects\P_Gatlin\jwt\keystore.jceks")
.setPassword("secret")
);
// Setup the secure route
authProvider = JWTAuth.create(vertx, config);
router.route().handler(BodyHandler.create());
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)).setAuthProvider(authProvider));
// Redirect to a login page if the user is NOT logged
var redirectAuthHandler = RedirectAuthHandler.create(authProvider, RouteNames.LOGIN_ADMIN, "/");
// Secure every page that starts with "/admin/..."
router.route("/admin/*").handler(redirectAuthHandler);
router.post(RouteNames.LOGIN_CHECKER).handler(FormLoginHandler.create(authProvider));
}
为了安全,我需要 /admin/*
路径。上面的实现几乎完全是从官方documentation复制粘贴过来的。我用这一行来生成密钥:
keytool -genkeypair -keystore keystore.jceks -storetype jceks -storepass secret -keyalg EC -keysize 256 -alias ES512 -keypass secret -sigalg SHA512withECDSA -dname "CN=,OU=,O=,L=,ST=,C=" -validity 360
从上面可以看出,密码是secret
,别名是es512
。这是登录页面的内容
<form action="/login-auth" method="POST">
<div class="credential">
<input type="text" name="username" placeholder="Username" />
<input type="password" name="password" placeholder="Password" />
<input type="submit" value="OK" />
</div>
</form>
其中 /login-auth
是 router.post(RouteNames.LOGIN_CHECKER).handler(FormLoginHandler.create(authProvider));
中 RouteNames.LOGIN_CHECKER
的值
在我的网页中,我尝试访问 http://localhost/admin/test
,我被正确重定向到 /login
页面:
为什么我会收到这条消息
Forbidden
我什么时候尝试访问?别名和密码是正确的,我还用 keytool 测试了它们并且它们匹配(我在命令中使用它们来生成 jceks)。怎么了?
我是否以某种方式未能使用 JWT 身份验证?
你在这里混合了 2 个不兼容的东西。
FormAuthHandler
功能是将您的浏览器重定向到 HTML 页面,其中 login/password 被询问给最终用户。这就是您所观察到的。
JWTHandler
功能是验证JWT令牌。
因此,当您的浏览器向服务器提交表单时,它会发送一个表单(带有 username/password),而不是 JWT 令牌。由于缺少令牌,您将收到禁止的错误代码。
场景
我在我的 HTTP 服务器 Verticle 的 start()
中调用此方法:
private void setupAuth(Router router) {
// Secure access key
var config = new JWTAuthOptions()
.setKeyStore(new KeyStoreOptions()
.setType("jceks")
.setPath("C:\Users\3587741\Desktop\Projects\P_Gatlin\jwt\keystore.jceks")
.setPassword("secret")
);
// Setup the secure route
authProvider = JWTAuth.create(vertx, config);
router.route().handler(BodyHandler.create());
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)).setAuthProvider(authProvider));
// Redirect to a login page if the user is NOT logged
var redirectAuthHandler = RedirectAuthHandler.create(authProvider, RouteNames.LOGIN_ADMIN, "/");
// Secure every page that starts with "/admin/..."
router.route("/admin/*").handler(redirectAuthHandler);
router.post(RouteNames.LOGIN_CHECKER).handler(FormLoginHandler.create(authProvider));
}
为了安全,我需要 /admin/*
路径。上面的实现几乎完全是从官方documentation复制粘贴过来的。我用这一行来生成密钥:
keytool -genkeypair -keystore keystore.jceks -storetype jceks -storepass secret -keyalg EC -keysize 256 -alias ES512 -keypass secret -sigalg SHA512withECDSA -dname "CN=,OU=,O=,L=,ST=,C=" -validity 360
从上面可以看出,密码是secret
,别名是es512
。这是登录页面的内容
<form action="/login-auth" method="POST">
<div class="credential">
<input type="text" name="username" placeholder="Username" />
<input type="password" name="password" placeholder="Password" />
<input type="submit" value="OK" />
</div>
</form>
其中 /login-auth
是 router.post(RouteNames.LOGIN_CHECKER).handler(FormLoginHandler.create(authProvider));
RouteNames.LOGIN_CHECKER
的值
在我的网页中,我尝试访问 http://localhost/admin/test
,我被正确重定向到 /login
页面:
为什么我会收到这条消息
Forbidden
我什么时候尝试访问?别名和密码是正确的,我还用 keytool 测试了它们并且它们匹配(我在命令中使用它们来生成 jceks)。怎么了?
我是否以某种方式未能使用 JWT 身份验证?
你在这里混合了 2 个不兼容的东西。
FormAuthHandler
功能是将您的浏览器重定向到 HTML 页面,其中 login/password 被询问给最终用户。这就是您所观察到的。JWTHandler
功能是验证JWT令牌。
因此,当您的浏览器向服务器提交表单时,它会发送一个表单(带有 username/password),而不是 JWT 令牌。由于缺少令牌,您将收到禁止的错误代码。