Tôi khá mới đối với Java và Spring 3 (sử dụng chủ yếu PHP trong 8 năm qua). Tôi đã nhận được an ninh mùa xuân 3 để làm việc với tất cả các userDetails mặc định và userDetailsService và tôi biết tôi có thể truy cập đăng nhập vào tên người dùng của người dùng trong một bộ điều khiển bằng cách sử dụng:Bảo mật mùa xuân: userdetails tùy chỉnh
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName(); //get logged in username
Nhưng có hai vấn đề tôi không thể hình ra:
Có rất nhiều chi tiết người dùng khác mà tôi muốn lưu khi người dùng đăng nhập (như DOB, giới tính, v.v.) và có thể truy cập được qua bộ điều khiển sau này. Tôi cần làm gì để đối tượng userDetails được tạo có chứa các trường tùy chỉnh của tôi?
Tôi đã gọi "HttpSession session = request.getSession (true);" ở đầu mỗi phương pháp trong bộ điều khiển của tôi. Có thể lưu trữ userDetails của người dùng đã đăng nhập trong một phiên khi đăng nhập để tôi không cần phải gọi "Authentication auth = SecurityContextHolder.getContext(). GetAuthentication();" ở đầu mỗi phương pháp?
Security-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" />
Cảm ơn Kent, điều đó khá hữu ích! Xin lỗi vì sự lộn xộn, lần đầu tiên mã hóa Spring. Tôi thích cách tiếp cận # 2, tôi sẽ đặt dòng mã đó ở đâu ở đầu mỗi phương pháp? Và tôi đoán dựa trên câu hỏi đó, nếu tôi đi với phương pháp thứ 2 đó là có thể lưu trữ đối tượng người dùng để tôi không ' t cần phải tạo một đối tượng người dùng mới và đi đến db cho cùng một dữ liệu mỗi lần? – Felix
Câu trả lời là, "nó phụ thuộc." Tôi thấy rằng với cách tiếp cận # 2, tôi rất hiếm khi cần truy cập vào tài khoản của người dùng (từ phối cảnh miền). Có lẽ tôi chỉ truy cập vào mục đích hiển thị hoặc chỉnh sửa "hồ sơ" của họ. Nếu đúng như vậy, tôi sẽ đọc qua kho dữ liệu cho thông tin này khi cần. Nếu bạn cần truy cập thường xuyên các thuộc tính của người dùng (từ phối cảnh tên miền; có lẽ một số thuộc tính của đối tượng người dùng cần xuất hiện trong tiêu đề và do đó cần thiết trong mọi yêu cầu), thì có thể bạn nên xem xét lại phương pháp # 1. –
Cảm ơn Kent. Tôi đã làm một giải pháp kiểu lai. Khi tôi cần người dùng đã đăng nhập, tôi chạy một phương thức trong trình điều khiển trình bao bọc để lấy dữ liệu. Phương thức này kiểm tra xem phiên có chứa một đối tượng người dùng hay không, và nếu nó kiểm tra nếu tên người dùng của đối tượng bằng với tên người dùng securityContext. Nếu không (hoặc nếu đối tượng người dùng phiên là null) nó sẽ lấy dữ liệu người dùng từ cơ sở dữ liệu và lưu trữ đối tượng trong phiên. Hai thêm nếu tuyên bố, nhưng 1 cuộc gọi cơ sở dữ liệu ít hơn. – Felix