当前版本:jdk1.8
、vert.x 4.2.4
1. 声明
当前内容主要为记录和学习使用Vert.x实现一个简单的登录访问控制操作的demo,当前内容参考:官方文档,这是一个非常简单的有意思的项目
主要功能:
- 实现非常简单登录功能
- 实现非常简单登出功能
- 实现访问控制(登录后方才可以访问)
- 实现基于Vert.x的session登录控制功能 (参考官方文档)
pom依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<vertx.version>4.2.4</vertx.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-stack-depchain</artifactId>
<version>${vertx.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
</dependency>
</dependencies>
2. 自定义登录控制的demo
1. 主要程序编写
import io.vertx.core.AbstractVerticle;
import io.vertx.core.MultiMap;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.web.Router;
public class MainVerticle extends AbstractVerticle {
boolean login = false;
@Override
public void start(Promise<Void> startPromise) throws Exception {
// Create a Router
Router router = Router.router(vertx);
// 登录操作
router.route("/login").handler(context->{
MultiMap queryParams = context.queryParams();
String username = queryParams.get("username");
String password = queryParams.get("password");
User user = User.create(new JsonObject().put("username", username).put("password", password));
context.setUser(user);
login=true;
context.json( new JsonObject().put("status", 200).put("msg", "login success!"));
});
// 所有的都需要登录验证才允许操作(认证操作)
router.route().handler(context->{
User user = context.user();
System.out.println(user);
if(!login){
System.out.println("认证用户失败!");
context.json( new JsonObject().put("status", 500).put("msg", "no login"));
}else {
// 直接放行执行下一个router
context.next();
}
});
router.route("/logout").handler(context->{
login=false;
context.json( new JsonObject().put("status", 200).put("msg", "login out success!"));
});
// 执行请求操作
router.route("/hello").method(HttpMethod.GET).handler(context->{
//context.json( new JsonObject().put("status", 200).put("msg", "ok"));
context.json(new JsonObject("{\"status\":200,\"msg\":\"ok\"}"));
});
// Create the HTTP server
vertx.createHttpServer()
.requestHandler(router)
.listen(8888)
.onSuccess(server ->
System.out.println(
"HTTP server started on port " + server.actualPort()
)
);
}
}
其中最主要的为context.next();
,表示放行的意思就是让下一个匹配的继续执行,注意login的router必须在全匹配登录验证的前面,否则login也会被拦截的
,这里设置无需密码就可登录,注意拦截router的顺序问题
2.部署程序
public class Application {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
// 直接部署一个vertx程序
vertx.deployVerticle(new MainVerticle());
}
}
3. 测试自定义登录demo
1.启动服务程序
直接访问受保护的,发现为500
进行登录操作
再次访问/hello
进行登出操作
再次访问/hello,再次被拦截
测试成功!
4. 基于Vert.x的Session机制的登录控制demo
该功能主要依赖Session实现,与前面的手动控制要好些
@Override
public void start(Promise<Void> startPromise) throws Exception {
// Create a Router
Router router = Router.router(vertx);
//bindLoginAndLogoutRouter(router);
router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
AuthenticationProvider authenticationProvider = new AuthenticationProvider() {
@Override
public void authenticate(JsonObject credentials, Handler<AsyncResult<User>> resultHandler) {
//String username = credentials.getString("username");
//String password = credentials.getString("password");
//System.out.println("username:"+username+",password="+password);
// 一个空的实现
}
};
// 处理登录界面,使用表单登录方式
//router.post("/login").handler(FormLoginHandler.create(authenticationProvider));
// Set a static server to serve static resources, e.g. the login page
// 开放登录静态页面
//router.route().handler(StaticHandler.create());
// 开始绑定登录路由
router.route("/login").handler(context->{
MultiMap queryParams = context.queryParams();
String username = queryParams.get("username");
String password = queryParams.get("password");
// 用户名密码为admin的才允许登录
if(username!=null&&password!=null&&"admin".equals(username.trim())&&"admin".equals(password.trim())) {
User user = User.create(new JsonObject().put("username", username).put("password", password));
context.setUser(user);
context.json( new JsonObject().put("status", 200).put("msg", "login success!"));
}else {
context.json( new JsonObject().put("status", 500).put("msg", "login failed!"));
}
});
router.route("/loginpage").handler(context->{
context.json( new JsonObject().put("status", 200).put("msg", "please login!"));
});
// 绑定认证路由
// 所有的都需要登录验证才允许操作(认证操作)
RedirectAuthHandler authHandler = RedirectAuthHandler.create(authenticationProvider);
router.route().handler(authHandler);
// 绑定登出路由
router.route("/logout").handler(context->{
// 清空已经登录的用户操作
context.clearUser();
context.json( new JsonObject().put("status", 200).put("msg", "login out success!"));
});
// 执行请求操作
router.route("/hello").method(HttpMethod.GET).handler(context->{
context.json(new JsonObject("{\"status\":200,\"msg\":\"ok\"}"));
});
// Create the HTTP server
vertx.createHttpServer()
// Handle every request using the router
.requestHandler(router)
// Start listening
.listen(8888)
// Print the port
.onSuccess(server ->
System.out.println(
"HTTP server started on port " + server.actualPort()
)
);
}
1.router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
表示开启session控制存储机制
只有开启Session并且打开认证提供,那么此时创建的User就是会在登录成功后保存在服务器中的
2. context.setUser(user);
表示设置认证的对象到服务器基于session方式
3. context.clearUser();
表示删除服务器中的session对应的user
4. /loginpage表示默认需要登录的位置,即登录失败后重定向的位置
测试访问/hello,直接被重定向到/loginpage地址了
错误的登录
正确的登录
登录后可以随意访问
退出登录
调试后发现这个:通过cookie进行控制的
测试成功!