Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
ziqian zhang
Grasscutter
Commits
39f23a0c
Commit
39f23a0c
authored
May 13, 2022
by
KingRainbow44
Browse files
Add new authentication system
parent
0b21a439
Changes
4
Show whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/auth/AuthenticationSystem.java
0 → 100644
View file @
39f23a0c
package
emu.grasscutter.auth
;
import
emu.grasscutter.server.http.objects.*
;
import
express.http.Request
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Getter
;
import
javax.annotation.Nullable
;
/**
* Defines an authenticator for the server.
* Can be changed by plugins.
*/
public
interface
AuthenticationSystem
{
/**
* Called when a user requests to make an account.
* @param username The provided username.
* @param password The provided password. (SHA-256'ed)
*/
void
createAccount
(
String
username
,
String
password
);
/**
* Called when a user requests to reset their password.
* @param username The username of the account to reset.
*/
void
resetPassword
(
String
username
);
/**
* This is the authenticator used for password authentication.
* @return An authenticator.
*/
Authenticator
<
LoginResultJson
>
getPasswordAuthenticator
();
/**
* This is the authenticator used for token authentication.
* @return An authenticator.
*/
Authenticator
<
LoginResultJson
>
getTokenAuthenticator
();
/**
* This is the authenticator used for session authentication.
* @return An authenticator.
*/
Authenticator
<
ComboTokenResJson
>
getSessionKeyAuthenticator
();
/**
* A data container that holds relevant data for authenticating a client.
* Call {@link AuthenticationRequest#builder()} to create a builder.
*/
@Builder
@AllArgsConstructor
@Getter
class
AuthenticationRequest
{
private
final
Request
request
;
@Nullable
private
final
LoginAccountRequestJson
passwordRequest
;
@Nullable
private
final
LoginTokenRequestJson
tokenRequest
;
@Nullable
private
final
ComboTokenReqJson
sessionKeyRequest
;
@Nullable
private
final
ComboTokenReqJson
.
LoginTokenData
sessionKeyData
;
}
/**
* Generates an authentication request from a {@link LoginAccountRequestJson} object.
* @param request The Express request.
* @param jsonData The JSON data.
* @return An authentication request.
*/
static
AuthenticationRequest
fromPasswordRequest
(
Request
request
,
LoginAccountRequestJson
jsonData
)
{
return
AuthenticationRequest
.
builder
()
.
request
(
request
)
.
passwordRequest
(
jsonData
)
.
build
();
}
/**
* Generates an authentication request from a {@link LoginTokenRequestJson} object.
* @param request The Express request.
* @param jsonData The JSON data.
* @return An authentication request.
*/
static
AuthenticationRequest
fromTokenRequest
(
Request
request
,
LoginTokenRequestJson
jsonData
)
{
return
AuthenticationRequest
.
builder
()
.
request
(
request
)
.
tokenRequest
(
jsonData
)
.
build
();
}
/**
* Generates an authentication request from a {@link ComboTokenReqJson} object.
* @param request The Express request.
* @param jsonData The JSON data.
* @return An authentication request.
*/
static
AuthenticationRequest
fromComboTokenRequest
(
Request
request
,
ComboTokenReqJson
jsonData
,
ComboTokenReqJson
.
LoginTokenData
tokenData
)
{
return
AuthenticationRequest
.
builder
()
.
request
(
request
)
.
sessionKeyRequest
(
jsonData
)
.
sessionKeyData
(
tokenData
)
.
build
();
}
}
src/main/java/emu/grasscutter/auth/Authenticator.java
0 → 100644
View file @
39f23a0c
package
emu.grasscutter.auth
;
import
emu.grasscutter.server.http.objects.*
;
/**
* Handles username/password authentication from the client.
* @param <T> The response object type. Should be {@link LoginResultJson} or {@link ComboTokenResJson}
*/
public
interface
Authenticator
<
T
>
{
/**
* Attempt to authenticate the client with the provided credentials.
* @param request The authentication request wrapped in a {@link AuthenticationSystem.AuthenticationRequest} object.
* @return The result of the login in an object.
*/
T
authenticate
(
AuthenticationSystem
.
AuthenticationRequest
request
);
}
\ No newline at end of file
src/main/java/emu/grasscutter/auth/DefaultAuthentication.java
0 → 100644
View file @
39f23a0c
package
emu.grasscutter.auth
;
import
emu.grasscutter.auth.DefaultAuthenticators.*
;
import
emu.grasscutter.server.http.objects.ComboTokenResJson
;
import
emu.grasscutter.server.http.objects.LoginResultJson
;
/**
* The default Grasscutter authentication implementation.
* Allows all users to access any account.
*/
public
final
class
DefaultAuthentication
implements
AuthenticationSystem
{
private
final
Authenticator
<
LoginResultJson
>
passwordAuthenticator
=
new
PasswordAuthenticator
();
private
final
Authenticator
<
LoginResultJson
>
tokenAuthenticator
=
new
TokenAuthenticator
();
private
final
Authenticator
<
ComboTokenResJson
>
sessionKeyAuthenticator
=
new
SessionKeyAuthenticator
();
@Override
public
void
createAccount
(
String
username
,
String
password
)
{
// Unhandled. The default authenticator doesn't store passwords.
}
@Override
public
void
resetPassword
(
String
username
)
{
// Unhandled. The default authenticator doesn't store passwords.
}
@Override
public
Authenticator
<
LoginResultJson
>
getPasswordAuthenticator
()
{
return
this
.
passwordAuthenticator
;
}
@Override
public
Authenticator
<
LoginResultJson
>
getTokenAuthenticator
()
{
return
this
.
tokenAuthenticator
;
}
@Override
public
Authenticator
<
ComboTokenResJson
>
getSessionKeyAuthenticator
()
{
return
this
.
sessionKeyAuthenticator
;
}
}
src/main/java/emu/grasscutter/auth/DefaultAuthenticators.java
0 → 100644
View file @
39f23a0c
package
emu.grasscutter.auth
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.server.http.objects.*
;
import
static
emu
.
grasscutter
.
Configuration
.*;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
/**
* A class containing default authenticators.
*/
public
final
class
DefaultAuthenticators
{
/**
* Handles the authentication request from the username & password form.
*/
public
static
class
PasswordAuthenticator
implements
Authenticator
<
LoginResultJson
>
{
@Override
public
LoginResultJson
authenticate
(
AuthenticationRequest
request
)
{
var
response
=
new
LoginResultJson
();
var
requestData
=
request
.
getPasswordRequest
();
assert
requestData
!=
null
;
// This should never be null.
boolean
successfulLogin
=
false
;
String
address
=
request
.
getRequest
().
ip
();
String
responseMessage
=
translate
(
"messages.dispatch.account.username_error"
);
// Get account from database.
Account
account
=
DatabaseHelper
.
getAccountByName
(
requestData
.
account
);
// Check if account exists.
if
(
account
==
null
&&
ACCOUNT
.
autoCreate
)
{
// This account has been created AUTOMATICALLY. There will be no permissions added.
account
=
DatabaseHelper
.
createAccountWithId
(
requestData
.
account
,
0
);
// Check if the account was created successfully.
if
(
account
==
null
)
{
responseMessage
=
translate
(
"messages.dispatch.account.username_create_error"
);
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.dispatch.account.account_login_create_error"
,
address
));
}
else
{
// Add default permissions.
for
(
var
permission
:
ACCOUNT
.
defaultPermissions
)
account
.
addPermission
(
permission
);
// Continue with login.
successfulLogin
=
true
;
// Log the creation.
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.dispatch.account.account_login_create_success"
,
address
,
response
.
data
.
account
.
uid
));
}
}
else
if
(
account
!=
null
)
successfulLogin
=
true
;
// Set response data.
if
(
successfulLogin
)
{
response
.
message
=
"OK"
;
response
.
data
.
account
.
uid
=
account
.
getId
();
response
.
data
.
account
.
token
=
account
.
generateSessionKey
();
response
.
data
.
account
.
email
=
account
.
getEmail
();
// Log the login.
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.dispatch.account.login_success"
,
address
,
account
.
getId
()));
}
else
{
response
.
retcode
=
-
201
;
response
.
message
=
responseMessage
;
// Log the failure.
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.dispatch.account.account_login_exist_error"
,
address
));
}
return
response
;
}
}
/**
* Handles the authentication request from the game when using a registry token.
*/
public
static
class
TokenAuthenticator
implements
Authenticator
<
LoginResultJson
>
{
@Override
public
LoginResultJson
authenticate
(
AuthenticationRequest
request
)
{
var
response
=
new
LoginResultJson
();
var
requestData
=
request
.
getTokenRequest
();
assert
requestData
!=
null
;
boolean
successfulLogin
;
String
address
=
request
.
getRequest
().
ip
();
// Log the attempt.
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.dispatch.account.login_token_attempt"
,
address
));
// Get account from database.
Account
account
=
DatabaseHelper
.
getAccountById
(
requestData
.
uid
);
// Check if account exists/token is valid.
successfulLogin
=
account
!=
null
&&
account
.
getSessionKey
().
equals
(
requestData
.
token
);
// Set response data.
if
(
successfulLogin
)
{
response
.
message
=
"OK"
;
response
.
data
.
account
.
uid
=
account
.
getId
();
response
.
data
.
account
.
token
=
account
.
getSessionKey
();
response
.
data
.
account
.
email
=
account
.
getEmail
();
// Log the login.
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.dispatch.account.login_token_success"
,
address
,
requestData
.
uid
));
}
else
{
response
.
retcode
=
-
201
;
response
.
message
=
translate
(
"messages.dispatch.account.account_cache_error"
);
// Log the failure.
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.dispatch.account.login_token_error"
,
address
));
}
return
response
;
}
}
/**
* Handles the authentication request from the game when using a combo token/session key.
*/
public
static
class
SessionKeyAuthenticator
implements
Authenticator
<
ComboTokenResJson
>
{
@Override
public
ComboTokenResJson
authenticate
(
AuthenticationRequest
request
)
{
var
response
=
new
ComboTokenResJson
();
var
requestData
=
request
.
getSessionKeyRequest
();
var
loginData
=
request
.
getSessionKeyData
();
assert
requestData
!=
null
;
assert
loginData
!=
null
;
boolean
successfulLogin
;
String
address
=
request
.
getRequest
().
ip
();
// Get account from database.
Account
account
=
DatabaseHelper
.
getAccountById
(
loginData
.
uid
);
// Check if account exists/token is valid.
successfulLogin
=
account
!=
null
&&
account
.
getSessionKey
().
equals
(
loginData
.
token
);
// Set response data.
if
(
successfulLogin
)
{
response
.
message
=
"OK"
;
response
.
data
.
open_id
=
account
.
getId
();
response
.
data
.
combo_id
=
"157795300"
;
response
.
data
.
combo_token
=
account
.
generateLoginToken
();
// Log the login.
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.dispatch.account.combo_token_success"
,
address
));
}
else
{
response
.
retcode
=
-
201
;
response
.
message
=
translate
(
"messages.dispatch.account.session_key_error"
);
// Log the failure.
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.dispatch.account.combo_token_error"
,
address
));
}
return
response
;
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment