我們正在開發一個帶有jQuery移動版的移動應用程序,並且想要在彈簧安全性正確設置的spring 3.1.x後端上以編程方式驗證用戶身份。春季安全:以編程方式登錄
POST請求被髮送到包含用戶名和密碼的後端(使用jQuery的$ .post),然後服務器驗證憑據是否正確並登錄到用戶。
服務器似乎在SecurityContext中正確設置了身份驗證,但是當我們向服務器發出第二個請求($ .get到需要登錄的頁面)時,安全細節似乎不會被記住,並且匿名令牌似乎在上下文中。
這是控制器處理登錄(簡潔,刪除密碼校驗)的方法:
@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;
}
}
這就是我們得到的UserDetails了上下文的另一種方法:
@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());
...
春季安全配置:
<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>
這要根據工作到春季安全文檔和其他在線資源。任何想法可能是錯誤的?
SecurityContextHolder默認保留策略是ThreadLocal。每個請求都在新線程中處理(實際上並不是每個線程池都是這樣,但這並不重要),並擁有自己的持有threadlocal的上下文副本。所以你在login方法中設置的身份驗證無法在getProjects方法中訪問(因爲它在另一個線程中)。你應該在某個地方保存你的認證信息(例如http會話),並在每次新的請求到達服務器時恢復認證對象(可能在servlet過濾器中) –
檢查http://stackoverflow.com/questions/3923296/user-granted -authorities-always-role-anonymous – axtavt
我使用由axtavt鏈接的出色答案實現了這個確切的功能。 –