Skip to main content

Route Access Permission Control

Introduction

This page introduces route access permissions. After reading it, you will be able to control whether clients can access specific actions.

For example, if you want to control access to a module, users should not directly access functions in that module. In traditional routing, these controls are often difficult or cumbersome, but here they are straightforward.

The framework provides precise access control, allowing you to specify which routes cannot be accessed by users. It also supports control by main route. For example, if you add control for main route 10, all actions under that main route become inaccessible externally.


Purpose of access control

  1. Prevent clients from accessing actions that do not exist on the server.
  2. Prevent clients from accessing non-public server actions.
  3. Prevent clients from accessing actions before login.

Usage Scenarios

Non-public routes

Suppose the server provides an action for increasing gold, but this action should be internal-only or GM-backend-only. If the client requests that route, the server returns a route-not-found error code.


Accessing business methods before login

Suppose a business method requires login. If a client accesses the action before login, the server returns a route-not-found error code.


Access control in the scenarios above is simple in this framework.

Route permission control is a common need. If an attacker forges requests whose routes do not exist on the server, it can be dangerous. With the framework's route permission control, this can be prevented effectively. For example, we can record how many times a client triggers non-existing routes, and when a threshold is reached, blacklist that IP for a period.

Example Source Code

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

path : ionet-cookbook-code

  • MyExternalServer

Settings

Strict Login and Route Access Control

Strict login means users cannot access any action unless logged in.

  • code 2: get the access control object.
  • code 4: indicates actions can be accessed only after login.
  • code 6: add actions that can be accessed without login.
private void extractedAccess() {
var accessAuthenticationHook = ExternalGlobalConfig.accessAuthenticationHook;
// Indicates that business methods can only be accessed after logging in
accessAuthenticationHook.setVerifyIdentity(true);
// Add - business methods (actions) that can be accessed without login (authentication)
accessAuthenticationHook.addIgnoreAuthCmd(HallCmd.cmd, HallCmd.loginVerify);
}

Denying User Access

Some actions are internal-only, such as adding gold or changing sensitive values. These actions must not be accessed directly from outside. "Outside" here refers to connected users.

  • code 4: add a precise route denied to users.
  • code 5: add a main route denied to users (range).
private void extractedAccess() {
var accessAuthenticationHook = ExternalGlobalConfig.accessAuthenticationHook;
// Add - control for rejecting player access
accessAuthenticationHook.addRejectionCmd(HallCmd.cmd, HallCmd.internalOffline);
accessAuthenticationHook.addRejectionCmd(InternalCmd.cmd);
}

From the code above, we can see two methods are provided: one for range route control and one for precise route control, so those routes cannot be directly accessed by real external users.

How to Use

class OneApplication {
static void main() {
extractedAccess();
...
new RunOne()
...
.startup();
}
}
warning

Route-permission logic must be placed in the external server, because permission control is performed there.

Further Reading: Discussion of Route Permission Design

There are usually two questions about route permission design:

  1. Why not add an attribute to ActionMethod for route rejection control?
  2. Why not add a new annotation on action methods?

These are common questions, so the design intent is explained in advance. Below is why route permission design uses AccessAuthenticationHook instead of extending ActionMethod.

Why Not Extend ActionMethod Attributes

Reasons for not extending ActionMethod attributes include:

  • Single responsibility.
  • Scattered configuration.
  • Framework stability impact.

Single responsibility

The single responsibility principle states each class/method should focus on one concern. However, extending attributes in ActionMethod introduces a series of problems. It increases annotation complexity, learning cost, maintenance cost, and coupling. For example, if similar features appear in the future, people may first try adding more attributes to ActionMethod. This attribute-growth style affects already stable code and clearly violates single responsibility.

In this case, after adding a "reject route" attribute to ActionMethod, people may also consider adding an attribute for routes accessible without login. If future features keep extending similarly, more attributes would continue to be added. When business volume is still small, this may seem acceptable. But once business complexity grows, issues become obvious. Maintenance cost and coupling increase, and onboarding cost for new developers also rises. You probably do not want to maintain or learn an annotation containing dozens of attributes.


Scattered configuration

If route rejection is configured via ActionMethod attributes, configuration becomes scattered and difficult to quickly review. By contrast, AccessAuthenticationHook centralizes configuration in one place, so it is easy to know which routes are configured.

With annotation-based coupling, it is hard to quickly identify routes with permission settings. Search tools can help, but the results are still scattered across files.


Framework stability impact

AccessAuthenticationHook supports range-based route rejection. If we modify ActionMethod, we would also need to change ActionController so it supports ranges. Changing previously stable code, with possible future changes again, increases instability risk. It also raises learning and usage cost.

Adding a new annotation for rejection can avoid this specific risk because it aligns with single responsibility, but a new annotation also has disadvantages, explained below.

Advantages of AccessAuthenticationHook

Compared with annotations, AccessAuthenticationHook has these advantages:

  • Avoids increasing annotation count.
  • More centralized configuration.
  • Better flexibility and emergency response.
  • Performance benefits.

Avoid increasing annotation count

AccessAuthenticationHook does not require adding a new annotation for route rejection. New annotations increase total framework annotation count and therefore increase learning cost. A single extra annotation may seem minor, but accumulation becomes significant.


More centralized configuration

Controlling permissions via annotations scatters configuration across action classes and methods. This increases maintenance cost, and reading code takes longer due to configuration fragmentation.

With AccessAuthenticationHook, configuration is centralized. You do not need to search everywhere to know which action class/method has permission rules.


Flexibility and emergency response

AccessAuthenticationHook can dynamically add/remove route rejection configuration without code changes or redeployments. This is useful in emergencies, for example when an action has a bug (such as infinite chest claiming). You can dynamically block user access to that route to avoid or reduce loss expansion.

Annotation-based approaches cannot do this. If annotation cannot support this capability, that annotation is optional at best, so adding a new annotation becomes unnecessary.


Performance benefit

AccessAuthenticationHook can reject requests at the external server, without letting requests reach logic servers, reducing network and server pressure.

Summary

In short, the reasons and advantages for using AccessAuthenticationHook instead of extending ActionMethod are mainly:

  • Not extending ActionMethod follows single responsibility, avoids scattered configuration, and avoids potential framework instability.
  • Using AccessAuthenticationHook reduces annotation count, centralizes management, and improves flexibility and performance.

This also explains why ActionController and ActionMethod are not extended with more attributes, and why a new annotation approach is not used.