Wir entwickeln eine mobile App mit jQuery mobile und möchten den Benutzer programmatisch auf einem Spring 3.1.x Backend authentifizieren, das korrekt mit Spring Security eingerichtet wurde.Spring security: programmgesteuert anmelden
Eine POST-Anfrage wird an das Backend gesendet (mit jQuery $ .post), die einen Benutzernamen und ein Passwort enthält, der Server überprüft dann, ob die Zugangsdaten korrekt sind und meldet den Benutzer an.
Der Server scheint die Authentifizierung in SecurityContext korrekt zu setzen. Wenn wir jedoch eine zweite Anfrage an den Server stellen (ein $ .get auf eine Seite, die eine Anmeldung erfordert), werden die Sicherheitsdetails nicht gespeichert und anonymisiert Token scheint in dem Kontext zu sein.
Dies ist die Methode in der Steuerung, die das Login (Passwort-Check für Kürze entfernt) Griffe:
@RequestMapping(value = "/login", method = RequestMethod.POST, produces = "application/json")
@ResponseBody
public Map<String, String> login(@RequestParam String username, @RequestParam String password, HttpServletRequest request) {
Map<String, String> response = new HashMap<String, String>();
User u = userService.findByAccountName(username);
if (u != null && u.hasRole("inspector")) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
try {
Authentication auth = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(auth);
response.put("status", "true");
return response;
} catch (BadCredentialsException ex) {
response.put("status", "false");
response.put("error", "Bad credentials");
return response;
}
} else {
response.put("status", "false");
response.put("error", "Invalid role");
return response;
}
}
Das ist die andere Methode, bei der wir die Userdetails aus dem Kontext erhalten:
@RequestMapping(value = "/project", method = RequestMethod.GET)
@ResponseBody
public String getProjects(HttpSession session) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
User u = userService.findByAccountName(((UserDetails) authentication.getPrincipal()).getUsername());
...
Frühling Sicherheitskonfiguration:
<global-method-security pre-post-annotations="enabled"/>
<http use-expressions="true" auto-config="true">
<form-login login-processing-url="/static/j_spring_security_check" login-page="/"
authentication-failure-url="/?login_error=t"/>
...
<intercept-url pattern="/api/**" access="permitAll"/>
...
<remember-me key="biKey" token-validity-seconds="2419200"/>
<logout logout-url="/logout"/>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="udm">
<password-encoder hash="md5"/>
</authentication-provider>
</authentication-manager>
Dies sollte nach Arbeit zur Frühjahrssicherheitsdokumentation und anderen Online-Ressourcen. Irgendwelche Ideen, was könnte falsch sein?
SecurityContextHolder Standard-Richtlinie ist ThreadLocal. Jede Anfrage wird in einem neuen Thread verarbeitet (eigentlich nicht bei allen Thread-Pools, aber das spielt keine Rolle) und hat eine eigene Kopie des Context-Threading-Locals. Daher kann auf Ihre Authentifizierung, die in der Anmeldemethode festgelegt wurde, nicht in der getProjects-Methode zugegriffen werden (weil sie in einem anderen Thread ist). Sie sollten Ihre Authentifizierungsinformationen an einem bestimmten Ort speichern (z. B. http-Sitzung) und das Authentifizierungsobjekt jedes Mal wiederherstellen, wenn eine neue Anfrage beim Server eingeht (wahrscheinlich im Servlet-Filter). –
Prüfen Sie http://stackoverflow.com/questions/3923296/user-granted -authorities-sind-immer-Rolle-anonym – axtavt
Ich implementierte diese genaue Funktionalität mit der ausgezeichneten Antwort von axtavt verbunden. –