21. Deprecated - iFun Authenticator

Attention

인증 에이전트에서 제공하는 기능들이 엔진 자체 기능으로 통합됨에 따라 아이펀 인증 에이전트 (iFun Authenticator) 프로그램은 더 이상 지원하지 않으며(Deprecated) 제거될 예정 입니다. 엔진에서 제공하는 인증 기능은 외부 서비스 지원 Part 1: 인증 검증 문서를 참고해주시기 바랍니다.

若使用Facebook、Google Plus等外部平台,为了执行用户验证,需要实现Client-side、erver-side两个阶段的认证。 在游戏客户端上运用相应平台的SDK进行验证,将可以识别认证事实的密钥传输给游戏服务器后,在游戏服务器上进行密钥的有效性检验。

大部分平台仅提供客户端认证,不提供服务器端的认证。 因此,联动的平台数量越多,给服务器开发商造成的负担越大。 iFun引擎提供了与主要平台之间的Server-side认证功能,以及导入好友列表、昵称等功能。

21.1. iFun Authenticator

iFun引擎使用名为 iFun Authenticator 的程序,作为专门负责认证的agent。 游戏服务器向iFun Authenticator发送认证验证请求,iFun Authenticator对不同平台进行验证。

Note

iFun引擎使用单独的认证agent是为了不影响游戏服务器,以便能够添加新的认证或更改认证。

同时,使用agent还可以使非游戏服务器的其他服务器通过agent的REST API来使用认证相关服务,因此十分便利。

21.1.1. 支持平台

支持如下外部平台的认证。(后续将持续添加可支持的外部平台)

  • Facebook

  • Twitter

  • Google+

  • Nexon Toy

21.1.2. 安装方法

Tip

游戏服务器端认证验证设置参数use_authenticator 设置为 false ,游戏服务器就会以批准所有认证验证请求的测试模式运行。 该设置在无需实际认证的开发初期阶段十分有用,此时无需安装iFun Authenticator。

21.1.2.1. Ubuntu环境

$ sudo apt-get update
$ sudo apt-get install funapi-authenticator1

21.1.2.2. CentOS环境

$ sudo yum install funapi-authenticator1

21.1.3. 运行方法

21.1.3.1. Ubuntu 14.04或Centos 6环境下

打开 /etc/default/funapi-authenticator 文件,修改为 enabled=1

然后执行以下命令。

$ sudo service funapi-authenticator start

21.1.3.2. Ubuntu 16.04或Centos 7环境下

执行以下命令。

$ sudo systemctl enable funapi-authenticator
$ sudo systemctl start funapi-authenticator

21.1.4. 查看任务

21.1.4.1. Ubuntu 14.04或Centos 6环境下

$ sudo service funapi-authenticator status

21.1.4.2. Ubuntu 16.04或Centos 7环境下

$ sudo systemctl status funapi-authenticator

21.1.4.3. Log文件

/var/log/funapi/funapi-authenticator/ 中生成日志文件。

21.1.5. iFun Authenticator设置方法(MANIFEST.json)

Note

该项目是iFun Authenticator自身的设置内容。使用iFun Authenticator设置游戏服务器时,请参考 游戏服务器端认证验证设置参数

iFun Authenticator也是通过iFun引擎编写的程序。 因此,iFun Authenticator也可以通过 MANIFEST.json 更改设置值。 iFun Authenticator的MANIFEST.json位于 /usr/share/funapi-authenticator/default/manifests/MANIFEST.json

可以指定如下设置值。

  • tcp_listen_port: 指定iFun引擎游戏服务器与iFun Authenticator通信时的TCP port编号。(type=uint16, default=12800)

  • http_listen_port: 指定通过REST API与iFun Authenticator通信时的HTTP port编号。(type=uint16, default=12801)

  • bypass: 是否无条件通过认证验证。使iFun Authenticator以测试模式运行。与在iFun引擎游戏服务器中指定为 use_authenticator=false 的效果相同。(type=bool, default=false)

  • ip_address_table_path: 指定含有可向iFun Authenticator发送请求的服务器IP地址的数据表文件路径。须指定 /usr/share/funapi-authenticator/default/resources/ 的相对路径。(type=string, default=”acl/ip_address_table”)

Tip

若更新代理,原来的MANIFEST.json将被覆盖。为了防止该问题,可以按照 临时重写MANIFEST.json 中的介绍,使用override文件。

/etc/funapi-authenticator/MANIFEST.override.json:

{
  "override": {
    "FunapiAuthenticatorServer": {
      "tcp_listen_port": 8070,
      "http_listen_port": 8080,
      ...
    },
    ...
  }
}

21.2. 认证验证

有使用iFun引擎提供的函数的方法(此时通过TCP通信),以及独立运用RESTful API的方法。

21.2.1. 在iFun引擎中调用函数的方法

iFun引擎使用单一的认证请求接口,与平台种类无关。 运用以下两个函数。分别是非同步、同步函数。

1
2
3
4
5
void Authenticate(const AccountAuthenticationRequest &request,
                  const AuthenticationResponseHandler &handler);

bool AuthenticateSync(const AccountAuthenticationRequest &request,
                      AccountAuthenticationResponse *response);
1
2
3
4
5
public static void Authenticate(Authentication.AccountAuthRequest request,
                                    Authentication.AuthResponseHandler handler);

public static bool AuthenticateSync(Authentication.AccountAuthRequest request,
                                        out Authentication.AccountAuthResponse response);

AccountAuthenticationRequest 객체를 생성하기 위해서는 다음과 같은 인자가 필요합니다.

1
2
3
AccountAuthenticationRequest(const string &service_provider,
                             const string &local_account,
                             const AuthenticationKey &key);
1
2
3
public AccountAuthRequest(string service_provider,
                          string local_account,
                          string auth_key);

각 인자에 대한 설명은 다음과 같습니다.

  • service_provider: 서비스 제공자를 지정하며 다음 인자 중 하나를 사용할 수 있습니다.

    • Facebook: Facebook 서비스

    • GooglePlus: Google+ 서비스

    • NexonToy: Nexon Toy 서비스

  • local_account: 사용자 계정을 판별할 수 있는 고유 식별자를 입력합니다. Facebook의 경우 uuid가 고유식별자가 될 수 있습니다.

  • key: 인증 정보를 담는 객체입니다. 플랫폼 별로 제공되는 다음 함수를 통해 생성할 수 있습니다.

1
2
3
4
5
6
7
8
9
AuthenticationKey MakeFacebookAuthenticationKey(const string &facebook_access_token)

AuthenticationKey MakeGooglePlusAuthenticationKey(const string &google_client_id,
                                                  const string &google_access_token)

AuthenticationKey MakeNexonToyAuthenticationKey(int64_t svc_id,
                                                const string &client_id,
                                                const string &np_sn,
                                                const string &np_token)
1
2
3
4
5
6
7
8
9
public static string MakeFacebookAuthKey(string facebook_access_token);

public static string MakeGooglePlusAuthKey(string google_client_id,
                                              string google_access_token);

public static string MakeNexonToyAuthKey(long svc_id,
                                             string client_id,
                                             string np_sn,
                                             string np_token);

Tip

更具体的内容请参考 API文件

21.2.1.1. 示例: Facebook认证验证

为进行Facebook认证,游戏客户端需访问Facebook认证服务器,输入Facebook ID和 密码,获取”access token”。游戏客户端 将该access token传输给游戏服务器后,游戏服务器可通过如下方式检验access token是否有效。

21.2.1.1.1. 同步方式

按如下所示,使用 AuthenticateSync()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void example(const string &fb_uid, const string &fb_access_token) {
  AuthenticationKey auth_key = MakeFacebookAuthenticationKey(access_token);

  // 아래는 인증 요청 정보를 만드는 것입니다.
  // 첫번째 인자는 인증 플랫폼 종류를 뜻합니다.
  AccountAuthenticationRequest req("Facebook", fb_uid, auth_key);
  AccountAuthenticationResponse rep;

  if (not AuthenticateSync(req, &rep)) {
    LOG(ERROR) << "authentication system error";
    return;
  }

  // 오류는 발생하지 않았지만, 인증 결과가 실패한 경우입니다.
  // 클라이언트가 가짜로 access token 을 만들어 보내는 경우 등이 포함됩니다.
  if (not rep.success) {
    LOG(INFO) << "login failed. code(" << rep.reason_code << "),"
              << "description(" << rep.reason_description << ")";
    return;
  }

  LOG(INFO) << "login success";
}
 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
// 클라이언트로부터 Facebook uid 와 access_token 을 전송 받았다고 가정하겠습니다.
public void Example(string fb_uid, string fb_access_token)
{
  string auth_key =
      Authentication.MakeFacebookAuthKey (fb_access_token);

  // 아래는 인증 요청 정보를 만드는 것입니다.
  // 첫번째 인자는 인증 플랫폼 종류를 뜻합니다.
  Authentication.AccountAuthRequest req =
      new Authentication.AccountAuthRequest (
          "Facebook", fb_uid, auth_key);
  Authentication.AccountAuthResponse rep;

  if (!Authentication.AuthenticateSync (req, out rep))
  {
    Log.Error ("authentication system error");
    return;
  }

  if (!rep.Success)
  {
    Log.Info ("login failed. code({0}), description({1})",
              rep.ReasonCode, rep.ReasonDescription);
    return;
  }

  Log.Info ("login success");
}
21.2.1.1.2. 非同步方式

按如下所示,使用 Authenticate()

 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
29
30
31
32
33
34
void OnLogin(
    const string &fb_uid,
    const AccountAuthenticationRequest &request,
    const AccountAuthenticationResponse &response,
    const bool &error) {
  // 인증 서버에서 오류가 발생한 경우입니다.
  if (error) {
    LOG(ERROR) << "authentication system error";
    return;
  }

  // 오류는 발생하지 않았지만, 인증 결과가 실패한 경우입니다.
  // 클라이언트가 가짜로 access token 을 만들어 보내는 경우 등이 포함됩니다.
  if (not response.success) {
    LOG(INFO) << "login failed. code(" << response.reason_code << "),"
              << "description(" << response.reason_description << ")";
    return;
  }

  LOG(INFO) << "login success: " << fb_uid;
}


void example(const string &fb_uid, const string &fb_access_token) {
  AuthenticationKey auth_key = MakeFacebookAuthenticationKey(access_token);

  // 인증 종류에 상관없이 아이펀 엔진은 단일한 인증 요청 인터페이스를 이용합니다.
  // 아래는 인증 요청 정보를 만드는 것입니다.
  AccountAuthenticationRequest req("Facebook", fb_uid, auth_key);

  AuthenticationResponseHandler callback = bind(&OnLogin, fb_uid, _1, _2, _3);

  Authenticate(request, callback);
}
 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public void OnLogin(
    string fb_uid,
    Authentication.AccountAuthRequest request,
    Authentication.AccountAuthResponse response,
    bool error)
{
  if (error)
  {
    Log.Error ("authentication system error");
    return;
  }

  if (!response.Success)
  {
    Log.Info ("login failed. code({0}), description({1})",
              response.ReasonCode, response.ReasonDescription);
    return;
  }

  Log.Info ("login success");
}

public void Example(string fb_uid, string fb_access_token)
{
  string auth_key =
      Authentication.MakeFacebookAuthKey (fb_access_token);

  // 인증 종류에 상관없이 아이펀 엔진은 단일한 인증 요청 인터페이스를 이용합니다.
  // 아래는 인증 요청 정보를 만드는 것입니다.
  Authentication.AccountAuthRequest req = new
      Authentication.AccountAuthRequest ("Facebook", fb_uid, auth_key);

  Authentication.Authenticate (
      req,
      (Authentication.AccountAuthRequest request,
       Authentication.AccountAuthResponse response,
       bool error) => {
    OnLogin(fb_uid, request, response, error);
  });

  // 아니면 아래처럼 delegate를 이용하여 콜백 핸들러를 등록할 수도 있습니다.
  // Authentication.AuthResponseHandler handler = (
  //     Authentication.AccountAuthRequest request,
  //     Authentication.AccountAuthResponse response,
  //     bool error) =>
  // {
  //   ...
  // };
  // Authentication.Authenticate (req, handler);
}

21.2.2. 利用REST API的方法

可以不使用iFun引擎,直接向iFun Authenticator请求REST API。 根据如下内容,以JSON format将各个参数包含在HTTP POST的body中,进行请求即可。

21.2.2.1. Test认证

在Test认证中,所有id值均认证成功。

POST /v1/authentication/test
Request JSON Object
  • player_id (string) – player_id

Response JSON Object
  • result (integer) –

    • 0: 认证成功

    • 1: 认证失败

    • 2: 参数错误

    • 其他: 其他错误

  • description (string) – 错误说明

21.2.2.2. Facebook平台认证

POST /v1/authentication/facebook
Request JSON Object
  • player_id (string) – Facebook uid

  • access_token (string) – Facebook access token

Response JSON Object
  • result (integer) –

    • 0: 认证成功

    • 1: 认证失败

    • 2: 参数错误

    • 其他: 其他错误

  • description (string) – 错误说明

21.2.2.2.1. 示例: Facebook认证验证
$ curl -X POST --data '{"player_id": "123...456", "access_token": "CAAC....tDZD"}' \
       http://localhost:12801/v1/authentication/facebook
{"result": 0, "description": ""}

21.2.2.3. IP基准认证

POST /v1/authentication/ipaddress
Request JSON Object
  • player_id (string) – 在ip认证中,所有id值均认证成功。

  • ip (string) – IP address

Response JSON Object
  • result (integer) –

    • 0: 认证成功

    • 1: 认证失败

    • 2: 参数错误

    • 其他: 其他错误

  • description (string) – 错误说明

21.3. 提取好友列表

有使用iFun引擎提供的函数的方法(此时通过TCP通信),以及独立运用RESTful API的方法。

21.3.1. 在iFun引擎中调用函数的方法

iFun引擎使用单一的好友列表请求接口,与平台种类无关。 运用以下两个函数。分别是非同步、同步函数。

void fun::GetPersonalInfo(const AccountPersonalInfoRequest &request,
                          const PersonalInfoResponseHandler &handler)

bool fun::GetPersonalInfoSync(const AccountPersonalInfoRequest &request,
                              AccountPersonalInfoResponse *response)

此时各个种类平台的差别只是生成 AccountPersonalInfoRequest 的方式不同。 为此,针对各个平台提供了以下Utility函数。

AuthenticationKey MakeFacebookAuthenticationKey(const string &facebook_access_token)

AuthenticationKey MakeGooglePlusAuthenticationKey(const string &google_client_id,
                                                  const string &google_access_token)

AuthenticationKey MakeNexonToyAuthenticationKey(int64_t svc_id,
                                                const string &client_id,
                                                const string &np_sn,
                                                const string &np_token)

Tip

更具体的内容请参考 API文件

21.3.1.1. 示例: 提取Facebook好友

21.3.1.1.1. 同步方式

按如下所示,使用 GetPersonInfoSync()

 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
void example(const string &fb_uid, const string &fb_access_token) {
  AuthenticationKey auth_key = MakeFacebookAuthenticationKey(access_token);

  // 사용자 정보 요청 메시지를 만듭니다.
  // 첫번째 인자는 외부 인증 종류를 의미합니다.
  AccountPersonalInfoRequest req("Facebook", fb_uid, auth_key);
  AccountPersonalInfoResponse rep;

  if (not GetPersonalInfoSync(req, &rep)) {
    LOG(ERROR) << "authentication system error";
    return;
  }

  // 오류는 발생하지 않았지만, 요청이 실패한 경우입니다.
  // 클라이언트가 가짜로 access token 을 만들어 보내는 경우 등이 포함됩니다.
  if (not rep.success) {
    LOG(INFO) << "request failed. code(" << rep.reason_code << "),"
              << "description(" << rep.reason_description << ")";
    return;
  }

  for (int i = 0; i < rep.friends.size(); ++i) {
    LOG(INFO) << "friend : " << rep.friends[i].id();
  }
}
 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
29
30
31
32
public void Example(string fb_uid, string fb_access_token)
{
  string auth_key =
      Authentication.MakeFacebookAuthKey (fb_access_token);

  // 사용자 정보 요청 메시지를 만듭니다.
  // 첫번째 인자는 외부 인증 종류를 의미합니다.
  Authentication.AccountPersonalInfoRequest req =
      new Authentication.AccountPersonalInfoRequest (
          "Facebook", fb_uid, auth_key);

  Authentication.AccountPersonalInfoResponse rep;

  if (!Authentication.GetPersonalInfoSync(req, out rep))
  {
    Log.Error ("authentication system error");
    return;
  }

  // 오류는 발생하지 않았지만, 요청이 실패한 경우입니다.
  // 클라이언트가 가짜로 access token 을 만들어 보내는 경우 등이 포함됩니다.
  if (!rep.Success) {
    Log.Info ("login failed. code({0}), description({1})",
              rep.ReasonCode, rep.ReasonDescription);
    return;
  }

  foreach (PlayerAccount account in rep.Friends)
  {
    Log.Info (account.Id);
  }
}
21.3.1.1.2. 非同步方式

在上述示例中,可使用 GetPersonInfo() 来代替 GetPersonInfoSync()

21.3.2. 利用REST API的方法

可以不使用iFun引擎,直接向iFun Authenticator请求REST API。 根据如下内容,以JSON format将各个参数包含在HTTP POST的body中,进行请求即可。

21.3.2.1. Test认证

POST /v1/personalinfo/test
Request JSON Object
  • player_id (string) – 在id、test认证中,所有id值均认证成功。

Response JSON Object
  • result (integer) –

    • 0: 成功

    • 1: 认证失败

    • 2: 参数错误

    • 其他: 其他错误

  • description (string) – 错误说明

  • friends (string[]) – 好友列表

21.3.2.2. Facebook平台

POST /v1/personalinfo/facebook
Request JSON Object
  • player_id (string) – Facebook uid

  • access_token (string) – Facebook access token

Response JSON Object
  • result (integer) –

    • 0: 成功

    • 1: 认证失败

    • 2: 参数错误

    • 其他: 其他错误

  • description (string) – 错误说明

  • friends (string[]) – 好友列表

21.3.2.2.1. 示例: 获取Facebook好友列表
$ curl -X POST --data '{"player_id": "123...456", "access_token": "CAAC....tDZD"}' \
       http://localhost:12801/v1/personalinfo/facebook
{"result": 0, "description": "", "friends": ["xx...x", "xx...x", ...,"xx...x"]}

21.4. 游戏服务器端认证验证设置参数

Note

该设置参数是使用iFun Authenticator的iFun引擎游戏服务器的值。iFun Authenticator自身的设置参数请参考 iFun Authenticator设置方法(MANIFEST.json)

  • use_authenticator: 是否激活与iFun Authenticator agent之间的通信。若为 false ,则bypass所有验证过程,并视为已经成功。(type=bool, default=false)

  • remote_authenticator_ip_address: iFun Authenticator运行的远程主机IP地址。(type=string, default=”0.0.0.0”)

  • remote_authenticator_port: iFun Authenticator运行的远程主机的端口编号。(type=uint64, default=0)