§ Session机制
本章节对fox-server 内session创建、还原、多节点session共享机制进行叙述
§ 创建
登录新建session,保存session信息到数据库
// 从当前线程获取session,true 表示没有则新建
Session session = SessionManager.getInstance().getSessionFromCurrentThread(true);
// 再次登录时,客户端有可能会携带seId字段,这样取到的session可能会是旧session,需要清空原有数据
session.clearData();
session.clearSystemData();
//设置session为登录状态
session.login(true);
//更新session最后操作时间
session.setLastOpsTime(System.currentTimeMillis());
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
§ 校验权限
在权限校验过滤器中对服务调用请求进行登录校验,如未登录则拒绝服务
§ 转存会话ID
在消息过滤器中,将会话id置入JsonRequest对象
在before方法中,根据不同消息来源,分别设置session id
TIP
HTTP请求
if (inBean instanceof HttpMessage){
HttpMessage httpMessage = (HttpMessage) inBean;
......
Object content = httpMessage.getContent();
// 如果入参为字符串转换为JSON对象
if (this.isJsonString(content)) {
String str = (String) content;
try {
// 解析JSON
Object obj = JSON.parse(str);
if (obj instanceof JSONObject) {
//取得httpMessage头中的sessionId字段
String sessionId = httpMessage.getHeader("sessionId");
JSONObject jsonObj = (JSONObject) obj;
// 获取请求头
JSONObject header = jsonObj.getJSONObject("header");
//将会话id设置头部中
header.put("seId", sessionId!=null?sessionId:"");
// 定义请求数据
JsonRequest request = new JsonRequest();
// 设置头
if (header != null) {
request.setHeaders(header);
}
......
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
TIP
SOCKET请求
if (inBean instanceof Message) {
Message message = (Message) inBean;
Object content = message.getContent();
if (this.isJsonString(content)) {
String str = (String) content;
try {
// 解析JSON
Object obj = JSON.parse(str);
if (obj instanceof JSONObject) {
JSONObject jsonObj = (JSONObject) obj;
// 获取请求头
JSONObject header = jsonObj.getJSONObject("header");
JsonRequest request = new JsonRequest();
// 将session id和socket来源地址设置到请求对象头部
if (header != null) {
String sessionId = message.getHeader("seId");
if (sessionId != null) {
header.put("seId", sessionId);
}
//获取socket来源地址
String source = message.getHeader("src");
if (source != null) { header.put("src", source);
}
request.setHeaders(header);
......
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
§ 会话校验
在权限过滤器中对session进行还原与校验
public void before(Event e) {
// 获取session
Session session = SessionManager.getInstance().getSessionFromCurrentThread(false);
// 判断session是否存在
if (session == null) {
//从JsonRequest对象头部取得sessionId
String sessionId = (String) request.getHeader("seId");
......
//从脚本根据sessionId 还原session
//如何设置脚本在下一小节进行介绍
session = SessionManager.getInstance().getSesssionFromScript(sessionId);
//对session状态进行判断
......
//更新数据表
......
}else{
//更新数据表
......
}
// 判断登录状态
Boolean loginStatus = session.isLogin();
if (!Boolean.TRUE.equals(loginStatus)) {
// 抛出异常
throw new Exception("unlogin");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
§ 服务加入权限校验
在对应服务接口的配置文件中,加入消息过滤器与权限过滤器,如filter-im-base.xml,filter-auth.xml
<!--继承的名字是文件名,继承的文件必须为abstract为true的文件 -->
<package name="im" namespace="account"
extends="filter-im-base.xml,filter-auth.xml">
1
2
3
2
3
§ 设置session创建脚本
应用启动时,应向session管理器中设置session创建脚本,该脚本从根据数据库中数据进行脚本还原,用于服务器多节点集群环境、或者长会话机制
在服务的init方法中设置session创建脚本,并将该服务设置为单例,onload=‘true’,建议该服务中不要添加过多接口,只加与登录相关接口
public void init() throws Exception {
SessionManager.getInstance().setCreateScript(new ICreateScript() {
//根据session id 创建session
public Session create(String id) {
try {
.....
//查询数据库会话表操作
//如存在继续创建session逻辑
//如不存在返回null
.....
// 还原session
Session session = SessionManager.getInstance().getSession(id,true);
// 设置登录
session.login(true);
//设置最后更新时间
session.setLastOpsTime(System.currentTimeMillis());
//设置session元数据
...
return session;
} catch (Exception e) {
LoggerUtil.error(e.getMessage(), e);
return null;
}
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
B I P!