Skip to main content

User Login

Introduction

This section introduces user login. After learning it, you can implement login, force login (kick previous session), and duplicate-login prevention.

Example Source Code

see https://github.com/iohao/ionet-examples

path : ionet-cookbook-code

  • HallAction

Login

Define protocol class UserMessage to return user info for login business.

  • code 7: flowContext.bindingUserId is the key login line. It sets real userId on external-server channel. After that, each user request can obtain user-related info via FlowContext.
@ActionController(HallCmd.cmd)
public class HallAction {
...
@ActionMethod(HallCmd.loginVerify)
private UserMessage loginVerify(String jwt, FlowContext flowContext) {
long userId = Math.abs(jwt.hashCode());

boolean success = flowContext.bindingUserId(userId);
ErrorCode.loginFailed.assertTrue(success);

return UserKit.ofUserMessage(userId);
}
}

@ToString
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class UserMessage {
long id;
String nickname;
}
warning

You must call this framework method to mark login verification as successful. Otherwise userId cannot be obtained from subsequent FlowContext.

Prevent Duplicate Login

Prevent duplicate login means the same account already online cannot log in again.

  • code 3: check whether user is online; if online, trigger assertion.
  • code 4: assertion + exception mechanism; if user is online, return error code to requester.
private UserMessage loginVerify(String jwt) {
long userId = Math.abs(jwt.hashCode());
boolean existUser = CommunicationKit.existUser(userId);
ErrorCode.userOnline.assertTrueThrows(existUser);
...
}

Force Login

Force login means the same account is already online, and the online session is kicked out.

  • code 3: force specific user offline.
private UserMessage loginVerify(String jwt) {
long userId = Math.abs(jwt.hashCode());
CommunicationKit.forcedOffline(userId);
...
}

UserId

After login, userId can be obtained through FlowContext.

public long hello(FlowContext flowContext) {
return flowContext.getUserId();
}

Can userId support String type?

Business requirement: What if userId is not long? For example, MongoDB objectId is String.

ionet is highly extensible and supports this requirement. Steps:

  1. Associate user data with a long id, e.g. Snowflake.
  2. Store objectId in meta information - attachment.
  3. Use custom FlowContext.
@ProtobufClass
@FieldDefaults(level = AccessLevel.PUBLIC)
public class MyAttachment {
long userId;
/** MongoDB objectId */
String objectId;
}

@Setter
@FieldDefaults(level = AccessLevel.PRIVATE)
public class MyFlowContext extends DefaultFlowContext {
MyAttachment attachment;

@Override
public MyAttachment getAttachment() {
if (Objects.isNull(this.attachment)) {
this.attachment = this.getAttachment(MyAttachment.class);
}

return this.attachment;
}

public String getUserIdString() {
var attachment = this.getAttachment(MyAttachment.class);
return attachment.objectId;
}
}