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;
}
}