[SPRING] 스프링 보안 : 맞춤형 사용자 상세 정보
SPRING스프링 보안 : 맞춤형 사용자 상세 정보
저는 Java와 Spring 3 (PHP는 지난 8 년 동안 주로 사용되었습니다)에 익숙하지 않았습니다. 모든 기본 userDetails 및 userDetailsService와 함께 작동하는 스프링 보안 3을 얻었으며 다음을 사용하여 컨트롤러에서 로그인 된 사용자의 사용자 이름에 액세스 할 수 있다는 것을 알고 있습니다.
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName(); //get logged in username
하지만 알아낼 수없는 두 가지 문제가 있습니다.
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" />
해결법
-
==============================
1.이 질문에 끔찍한 일이 많이 있습니다. 나는 그것을 조각으로 다루려고 노력할 것이다 ...
이 질문에 끔찍한 일이 많이 있습니다. 나는 그것을 조각으로 다루려고 노력할 것이다 ...
Q # 1 : 가능한 접근법이 몇 가지 있습니다.
접근법 # 1 : UserDetails 객체에 추가하려는 다른 속성이있는 경우 해당 속성을 포함하는 UserDetails 인터페이스의 대체 구현을 해당 getter 및 setter와 함께 제공해야합니다. 이렇게하려면 UserDetailsService 인터페이스의 대체 구현을 제공해야합니다. 이 구성 요소는 기본 데이터 저장소에 이러한 추가 특성을 유지하는 방법을 이해해야하거나 해당 데이터 저장소에서 읽을 때 추가 특성을 채우는 방법을 이해해야합니다. 이 모든 것을 이렇게 연결합니다.
<beans:bean id="userDetailsService" class="com.example.MyCustomeUserDetailsService"> <!-- ... --> </beans:bean> <authentication-manager alias="authenticationManager"> <authentication-provider ref="authenticationProvider"/> </authentication-manager> <beans:bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> <beans:property name="userDetailsService" ref="userDetailsService"/> </beans:bean>
Approaches # 2 : 나처럼 스프링 보안에 특정한 사용자 / 계정 세부 사항과는 별도로 도메인 특정 사용자 / 계정 세부 사항을 유지하는 것이 더 낫다는 것을 발견 할 수있다. 이것은 당신을 위해 또는 그렇지 않을 수도 있습니다. 그러나이 접근법에서 어떤 지혜를 찾을 수 있다면 현재 가지고있는 설정을 고수하고 추가 사용자 / 계정 도메인 객체, 해당 저장소 / DAO 등을 추가 할 것입니다. 도메인 별 사용자 / 계정을 만들려면 다음과 같이하십시오.
User user = userDao.getByUsername(SecurityContextHolder.getContext().getAuthentication().getName());
Q # 2 : Spring Security는 자동으로 UserDetails를 세션에 저장합니다 (명시 적으로 해당 동작을 재정의하지 않은 경우 제외). 따라서 각 컨트롤러 메소드에서 직접이 작업을 수행 할 필요는 없습니다. 처리중인 SecurityContextHolder 객체는 실제로 모든 요청이 시작될 때 Authentication 객체, UserDetails 등을 포함하여 SecurityContext로 (SS별로) 채워집니다. 이 컨텍스트는 각 요청이 끝날 때 지워지지만 데이터는 항상 세션에 남아 있습니다.
그러나 Spring MVC 컨트롤러에서 HttpServletRequest, HttpSession 객체 등을 다루는 것이 실제로는 좋은 습관은 아니라는 것을주의해야한다. Spring은 거의 항상 그 일을 할 필요없이 더 깨끗하고 더 관용적 인 방법을 제공합니다. 그 장점은 컨트롤러 메소드의 서명과 로직이 유닛 테스트 (예 : HttpSession)에서 모의하기가 어렵고 자신의 도메인 객체 (또는 해당 도메인 객체의 스텁 / 모의 객체)에 의존하지 않고 중단된다는 것입니다 ). 이렇게하면 컨트롤러의 테스트 가능성이 크게 높아져 실제로 컨트롤러를 테스트 할 가능성이 높아집니다. :)
희망이 좀 도움이됩니다.
-
==============================
2.내 생각에, 사용자 정의 UserDetails 구현은 훌륭하지만 사용자의 불변 특성에만 사용해야합니다.
내 생각에, 사용자 정의 UserDetails 구현은 훌륭하지만 사용자의 불변 특성에만 사용해야합니다.
사용자 정의 사용자 객체가 UserDetails를 재정의하면 쉽게 변경되지 않습니다. 수정 된 세부 정보로 완전히 새로운 인증 개체를 만들어야하며 수정 된 UserDetails 개체를 보안 컨텍스트에 다시 붙일 수 없습니다.
내가 구현하고있는 응용 프로그램에서 나는 이것을 깨닫고 그것을 재 설계해야만합니다. 그래서 모든 요청에 따라 변경되는 사용자에 대한 성공적인 인증 세부 사항 (모든 페이지로드시 DB에서 다시로드하지 않으려 고합니다) 세션에 별도로 보관해야하지만 인증 확인 후에는 액세스 가능 / 변경 가능해야합니다.
https://stackoverflow.com/a/8769670/1411545에서 언급 한이 WebArgumentResolver가 내 상황에 대한 더 나은 솔루션인지 파악하려고합니다.
-
==============================
3.세션에 직접 액세스하는 것은 약간 지저분하고 오류가 발생할 수 있습니다. 예를 들어, 사용자가 remember-me 또는 리디렉션을 포함하지 않는 다른 메커니즘을 사용하여 인증 된 경우 해당 요청이 완료 될 때까지 세션이 채워지지 않습니다.
세션에 직접 액세스하는 것은 약간 지저분하고 오류가 발생할 수 있습니다. 예를 들어, 사용자가 remember-me 또는 리디렉션을 포함하지 않는 다른 메커니즘을 사용하여 인증 된 경우 해당 요청이 완료 될 때까지 세션이 채워지지 않습니다.
사용자 지정 액세서 인터페이스를 사용하여 SecurityContextHolder에 대한 호출을 래핑합니다. 이 관련된 질문에 대한 내 대답을 참조하십시오.
from https://stackoverflow.com/questions/10607696/spring-security-custom-userdetails by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] JPA @OneToMany -> 부모 - 하위 참조 (외래 키) (0) | 2019.01.10 |
---|---|
[SPRING] @RunWith 및 @ContextConfiguration 주석이 달린 jUnit 테스트에서 Spring 컨텍스트에 액세스하는 방법? (0) | 2019.01.10 |
[SPRING] Spring Batch Admin을 기존 애플리케이션에 통합 (0) | 2019.01.10 |
[SPRING] Tomcat 서버에 스프링 부트 웹 응용 프로그램을 배포하는 방법 (0) | 2019.01.10 |
[SPRING] JDBC 템플릿 용으로 어떤 트랜잭션 관리자를 사용해야합니까? JPA를 사용할 때? (0) | 2019.01.10 |