关于本话题最基本的应用就是登录了,个人今天做了一个登录的小案例,有些小心得分享一下。
基本知识
- 首先,
cookie
是我们用来发送到客户端的数据,由于http协议本身是无状态的,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息(key-value格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie
。客户端浏览器会把Cookie
保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie
一同提交给服务器。服务器检查该Cookie
,以此来辨认用户状态
session
:session
机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(key-value
)来保存信息。 一般来说,服务器第一次接收到请求时,开辟了一块Session
空间(创建了Session
对象),同时生成一个Session id
,并通过响应头的Set-Cookie:“JSESSIONID=XXXXXXX”
命令(此处的cookie
为tomcat
或者undertow
示例的cookie
),向客户端发送要求设置cookie
的响应。
- 维持一段会话靠的是
cookie
和session
都存在的情况下,如果cookie
设置了维持的时间,则到时间后会自动清空,session
如果删除了所存储的sessionId
,则也是。
基本操作
- 基于上面的方式,我们对于一个登录成功的用户,可以使用加密方式获得一个
sessionId
,将sessionId
和对应的用户信息可以放入session
中,也可以放入类似redis
的缓存共享空间中,加上其对应的过期时间,或者某些情况下手动删除。
- 将此
sessionId
设置到cookie
中,这样每次请求都会附带上这些信息,我们就可以在服务端查找该id
对应的信息了,再简单加上拦截器即可判断是否登录。
jfinal简单案例代码
@Before(LoginValidator.class)
public void login() {
String cookie = getCookie(LoginService.SESSION_ID);
if (cookie != null && getSessionAttr(cookie) != null) {
render("/index/index.html");
}
User user = getBean(User.class, "");
Ret ret = service.login(user);
if (ret.isOk()) {
String sessionId = StrKit.getRandomUUID();
setSessionAttr(sessionId, ret.get(LoginService.CACHE_KEY));
setCookie(LoginService.SESSION_ID, sessionId, 1 * 60 * 60, true);
set("name", user.getName());
render("/index/index.html");
} else {
set("mes", ret.get("mes"));
render("login.html");
}
}
public class LoginInterceptor implements Interceptor {
@Override
public void intercept(Invocation inv) {
User user;
Controller controller = inv.getController();
String sessionId = controller.getCookie(LoginService.SESSION_ID);
if (sessionId != null) {
user = controller.getSessionAttr(sessionId);
if (user != null) {
user.hide();
controller.set("name", user.getName());
} else {
controller.removeCookie(LoginService.SESSION_ID);
}
}
inv.invoke();
}
}
public class LoginService {
private User dao = new User().dao();
public static final String SESSION_ID = "sessionId";
public static final String CACHE_KEY = "user";
public Ret login(User user) {
User result = dao.findFirst("select * from user where name = ?",
user.getName());
if (result != null) {
if (result.getPwd().equals(user.getPwd())) {
return Ret.ok().set(LoginService.CACHE_KEY, user);
} else {
return Ret.fail("mes", "密码不正确");
}
} else {
return Ret.fail("mes", "不存在此用户");
}
}
}
小提示
- 基本的
httpservletRequest
和httpservletResponse
,Java
只提供了接口,所以这些具体实现类需要服务器自己写,例如Tomcat
,undertow
服务器,这些实现类是它们实现的。