0

我想要实现的是,使用 Raygun(一种崩溃报告服务)向遇到问题的用户发送用户详细信息。

我最初尝试使用类似于此的方法来获取用户名:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
username = authentication.getName();

但是由于某种原因,这返回了值,ipaduser. 我不确定该值来自何处,但这显然不是答案。

然后我尝试了:

System.getProperty("user.name");

但这只是获取我们 API 服务器的登录用户的名称,而不是使用应用程序的用户的用户名。

经过一番挖掘,我发现用户的用户名和数据库名称存储在一个名为 ApiAccessToken 的自定义对象中。问题是,这个 ApiAccessToken 对象只在我们的 Controller 类的方法中设置。

例如:

@RequestMapping(path = "/api/foo", method = RequestMethod.GET)
public List<Bar> getBarForDatabase(@RequestParam(value = "api_key") String apiKey{
    ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey);
    // Etc
}

ApiAccessToken 和 validateApiKey() 的代码如下:

public final class ApiAccessToken {

    private String databaseName;
    private String username;

    public String getDatabaseName() { return databaseName; }

    public void setDatabaseName(String databaseName) { this.databaseName = databaseName; }

    public String getUsername() { return username; }

    public void setUsername(String username) { this.username = username; }
}

protected ApiAccessToken validateApiKey(ApiKeyService apiKeyService, String apiKey){
    UserAccountJdbcRepository userAccountJdbcRepository = new UserAccountJdbcRepository(createDataSourceForDatabase(USERS_DATABASE_NAME));
    ApiAccessToken accessToken = apiKeyService.validateApiKey(userAccountJdbcRepository, apiKey);
    if (accessToken == null) {
        throw new InvalidApiKeyException();
    }
    return  accessToken;
}

我的另一个想法是在 Controller 类中有一个局部变量来存储 的值,apiKey然后我会使用 getter 将该值传递给另一个方法。例如,在 Controller 类中:

private static String apiKey;

public static String getApiKey() { return apiKey; }

@RequestMapping(path = "/api/foo", method = RequestMethod.GET)
public List<Bar> getBarForDatabase(@RequestParam(value = "api_key") String apiKey{
    ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey);
    apiKey = this.apiKey; 
    //Etc
}

然后在我向 Raygun 发送异常详细信息的课程中:

 String apiKey = Controller.getApiKey();
 ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey);
 username = accessToken.getUsername();
 database = accessToken.getDatabaseName();

但这只会返回 NullPointerException 并且不会向 Raygun 发送任何内容。

任何帮助将不胜感激,因为我不完全确定还能尝试什么。让我知道我是否遗漏了您认为我应该包括的任何内容。再一次,我对 Spring MVC 还是很陌生,编写大部分内容的开发人员不再受雇于我们。

4

2 回答 2

1

由于 api_key 是一个请求参数,因此您获得它的唯一方法是通过控制器。

class Controller {

    @RequestMapping(path = "/api/foo", method = RequestMethod.GET)
    public List<Bar> getBarForDatabase(@RequestParam(value = "api_key") String apiKey) {
        ...

        Raygun.sendException(apiKey)
        ...
    }
}

class Raygun {
     public static sendException(String apiKey) {
         ApiAccessToken accessToken = validateApiKey(apiKeyService, apiKey);
         username = accessToken.getUsername();
         database = accessToken.getDatabaseName();
         ...
     }
}

如果您想在多个地方使用 api key 获取用户信息,请查看Interceptor

于 2016-12-01T15:41:08.747 回答
0

在 Minh Hoang 的建议下,我能够解决这个问题。

我在 RaygunUnhandledExceptionHandler 类中添加了一个全局变量:

private static ApiAccessToken accessToken = new ApiAccessToken();

然后我在 RaygunUnhandledExceptionHandler 中编写了这个方法来获取accessToken并将其设置为我在上面声明的变量:

public static void getAccessTokenFromController(ApiAccessToken accessTokenFromController) { accessToken = accessTokenFromController; }

然后我将此行添加到 Controller 中的 /api/foo 以便它将发送accesstoken到 RaygunUnhandledExceptionHandler:

// Sends the API Key to RaygunUnhandledExceptionHandler
RaygunUnhandledExceptionHandler.getAccessTokenFromController(accessToken);

然后在 RaygunUnhandledExceptionHandler 的 defaultErrorHandler() 中:

ArrayList tags = new ArrayList<String>();
tags.add("username: " + accessToken.getUsername());
tags.add("database: " + accessToken.getDatabaseName());


再次感谢 Minh Hoang 和 fantaghirocco 帮助我解决这个问题。

如果您发现此实现有任何问题,请告诉我。

于 2016-12-02T00:45:34.210 回答