2016-12-01 1 views
0

Bitte nimm mich mit, da ich keine Erfahrung mit Spring MVC hatte, bis ich vor nicht allzu langer Zeit mit meinem neuen Job angefangen habe andere Entwickler. Dies wird auch eine ziemlich lange Frage sein (ich habe einige meiner Beispiele vereinfacht, damit sie hoffentlich nicht zu lang sind).SpringMVC/JAVA - Erhalte den Parameterwert von der Methode in einer anderen Klasse

Was ich versuche zu erreichen ist, Raygun (ein Absturz-Reporting-Dienst), senden Sie die Benutzerdetails des Benutzers, der das Problem erlebt.

Ich habe versucht, ursprünglich ein ähnliches Verfahren wie das mit dem Benutzernamen zu erhalten:

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

Aber aus irgendeinem Grund den Wert zurückgegeben, ipaduser. Ich bin mir nicht sicher, woher dieser Wert kommt, aber das ist offensichtlich nicht die Antwort.

ich dann versucht:

System.getProperty("user.name"); 

Aber das bekommt nur den Namen des angemeldeten Benutzers für unsere API-Server, nicht den Benutzernamen des Benutzers, die Anwendung.

Nach einigen Umgrabungen entdeckte ich, dass der Benutzername und der Name der Datenbank für einen Benutzer in einem benutzerdefinierten Objekt namens ApiAccessToken gespeichert werden. Das Problem ist, dass dieses ApiAccessToken-Objekt nur in Methoden in unseren Controller-Klassen festgelegt wird.

Zum Beispiel:

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

Der Code für ApiAccessToken und validateApiKey() sind wie folgt:

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

Und

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

Meine andere Idee, eine lokale Variable wurde mit in die Controller-Klasse, die den Wert von apiKey speichern würde und dann würde ich pa ss, die für die andere Methode einen Getter verwenden. Zum Beispiel in der Controller-Klasse:

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 
} 

Und dann in der Klasse, wo ich Ausnahme Details Raygun bin das Senden:

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

Aber das gibt nur eine Nullpointer und sendet nichts zu Strahlenpistole.

Jede Hilfe würde sehr geschätzt werden, da ich nicht ganz sicher bin, was ich sonst noch versuchen sollte. Lass es mich wissen, wenn ich etwas ausgelassen habe, von dem du denkst, ich sollte es mit einschließen. Wieder einmal bin ich bei Spring MVC noch ziemlich neu und der Entwickler, der das meiste geschrieben hat, ist nicht mehr bei uns beschäftigt.

Danke,

Cale B

+1

'((ApiAccessToken) SecurityContextHolder.getContext(). GetAuthentication(). GetPrincipal()). GetName()' funktioniert? Trotzdem sollte der Benutzer 'SecurityContextHolder.getContext() sein. GetAuthe nication(). GetPrinc ipal()' – fantaghirocco

+0

@fantaghirocco Leider nicht. Mit '((ApiAccessToken) SecurityContextHolder.getContext(). GetAuthentication(). GetPrincipal()). GetUsername()', bekomme ich den Fehler "Fehler beim Aufruf von @ExceptionHandler Methode: public org.springframework.web.servlet.ModelAndView au. com.pdsonline.sync.integration.exception.RaygunUnhandledExceptionHandler.defaultErrorHandler (javax.servlet.http.HttpServletRequest, java.lang.Exception) gibt java.lang.Exception aus java.lang.ClassCastException: org.springframework.security.core. userdetails.User kann nicht in ApiAccessToken umgewandelt werden " –

+0

oops ... sorry:' UserDetails userDetail = (UserDetails) SecurityContextHolder.getContext(). getAuthe nication(). get Princ ipal(); 'und' userDetail.getUsername (); ' – fantaghirocco

Antwort

0

Mit dem Vorschlag von Minh Hoang, ich war in der Lage, dieses Problem zu lösen.

Ich habe eine globale Variable in die Klasse RaygunUnhandledExceptionHandler:

private static ApiAccessToken accessToken = new ApiAccessToken(); 

ich diese Methode dann in RaygunUnhandledExceptionHandler schrieb die accessToken und legen Sie es auf die Variable zu bekommen ich oben erklärt:

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

I dann fügte diese Zeile zu/api/foo in der Steuerung hinzu, so dass es die accesstoken an RaygunUnhandledExceptionHandler senden würde:

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

Und dann in defaultErrorHandler() in RaygunUnhandledExceptionHandler:

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


Nochmals vielen Dank an Minh Hoang und fantaghirocco für Ihre Unterstützung dieser in aushelfen mich sortieren.

Bitte lassen Sie mich wissen, wenn Sie Probleme mit dieser Implementierung sehen.

1

Als api_key ein Anforderungsparameter ist, der einzige Weg, es ist durch den Controller bekommen.

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(); 
     ... 
    } 
} 

Wenn Sie die Benutzerinformationen mit api Schlüssel an mehreren Stellen erhalten möchten, werfen Sie einen Blick auf Interceptor

+0

Vielen Dank, obwohl nicht die richtige Implementierung benötigt, haben Sie mich auf dem richtigen Weg und war in der Lage, dieses Problem zu lösen :) Ich werde eine Antwort enthalten, um zu zeigen, was ich anders gemacht habe .. –

Verwandte Themen