我對Java和Spring 3(過去8年主要使用PHP)非常新穎。我已經得到了春季安全3所有默認爲userDetails和UserDetailsService的工作,我知道我可以通過訪問登錄的用戶的用戶名控制器:Spring Security:自定義用戶代碼
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName(); //get logged in username
但有兩個問題我想不通出:
有很多的其他用戶的信息我想存儲當在用戶登錄(如DOB,性別等),並且是經由控制器稍後訪問。我需要做什麼以便創建的userDetails對象包含我的自定義字段?
我已經調用了「HttpSession session = request.getSession(true);」在我的控制器中的每個方法的頂部。是否有可能在登錄時將登錄用戶的userDetails存儲在會話中,以便我不需要同時調用「Authentication auth = SecurityContextHolder.getContext()。getAuthentication();」在每種方法的開始?
安全-的applicationContext.xml:
<global-method-security secured-annotations="enabled"></global-method-security>
<http auto-config='true' access-denied-page="/access-denied.html">
<!-- NO RESTRICTIONS -->
<intercept-url pattern="/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/*.html" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<!-- RESTRICTED PAGES -->
<intercept-url pattern="/admin/*.html" access="ROLE_ADMIN" />
<intercept-url pattern="/member/*.html" access="ROLE_ADMIN, ROLE_STAFF" />
<form-login login-page="/login.html"
login-processing-url="/loginProcess"
authentication-failure-url="/login.html?login_error=1"
default-target-url="/member/home.html" />
<logout logout-success-url="/login.html"/>
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource" authorities-by-username-query="SELECT U.username, UR.authority, U.userid FROM users U, userroles UR WHERE U.username=? AND U.roleid=UR.roleid LIMIT 1" />
<password-encoder hash="md5"/>
</authentication-provider>
</authentication-manager>
的login.jsp:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<tiles:insertDefinition name="header" />
<tiles:insertDefinition name="menu" />
<tiles:insertDefinition name="prebody" />
<h1>Login</h1>
<c:if test="${not empty param.login_error}">
<font color="red"><c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}"/>.<br /><br /></font>
</c:if>
<form name="f" action="<c:url value='/loginProcess'/>" method="POST">
<table>
<tr><td>User:</td><td><input type='text' name='j_username' value='<c:if test="${not empty param.login_error}"><c:out value="${SPRING_SECURITY_LAST_USERNAME}"/></c:if>' /></td></tr>
<tr><td>Password:</td><td><input type='password' name='j_password' /></td></tr>
<tr><td> </td><td><input type="checkbox" name="_spring_security_remember_me" /> Remember Me</td></tr>
<tr><td> </td><td><input name="submit" type="submit" value="Login" /></td></tr>
</table>
</form>
<tiles:insertDefinition name="postbody" />
<tiles:insertDefinition name="footer" />
謝謝Kent,這非常有幫助!對不起,第一次編碼Spring。我喜歡方法#2,我會在哪裏放置那行代碼,在每個方法的開始處?我想基於這個問題,如果我採用第二種方法,可以存儲用戶對象,是否需要創建一個新的用戶對象,並每次都去相同的數據分貝? – Felix
答案是,「這取決於」。我發現通過方法#2,我很少需要訪問用戶的帳戶(從域角度來看)。也許我只是爲了顯示或編輯他們的「個人資料」而訪問它。如果是這樣的話,我會在需要時通讀數據存儲庫以獲取此信息。 但是,如果您需要經常訪問用戶的屬性(從域的角度來看,可能某些用戶對象的屬性需要出現在標題中,因此在每個請求中都需要),那麼您可能應該重新考慮方法#1。 –
謝謝肯特。我最終做了一個混合型解決方案。當我需要登錄的用戶時,我在包裝控制器中運行一個方法來獲取數據。該方法檢查會話中是否包含用戶對象,如果是,則檢查該對象的用戶名是否等於securityContext用戶名的用戶名。如果不是(或者如果會話用戶對象爲空),則它從數據庫獲取用戶數據並將該對象存儲在會話中。兩個額外的if語句,但少一個數據庫調用。 – Felix