SpringSecurity 사용 기록 (5) -- 설정
21696 단어 SpringSecurity
namespace (security 3.0 입 니 다. 인터넷 에서 도 일부 형제 가 묘사 한 것 은 3.0 이지 만 항상 제 가 있 는 namespace 설정 에 부합 되 지 않 습 니 다):
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
기본 설정 http (namespace 설정 에 따 른 기본 보안 필터 chain):
auto - config = true
기본 필 터 를 사용 한 것 이다.
내 가 처음에 생각 한 것 은 로 컬 login 정보 (spring security 를 호출 하 는 login 방법 이 아 닌) 를 spring security 의 검증 필터 에 전송 하 는 것 이다.
여기 서 가장 중요 한 문 제 는 필 터 를 밀봉 하 는 것 입 니 다. (또는 그들 이 어떤 필터 가 작용 하 는 지 만 알 고 있 습 니 다)
Alias
Filter Class
Namespace Element or Attribute
CHANNEL_FILTER
ChannelProcessingFilter
http/intercept-url@requires-channel
CONCURRENT_SESSION_FILTER
ConcurrentSessionFilter
session-management/concurrency-control
SECURITY_CONTEXT_FILTER
SecurityContextPersistenceFilter
http
LOGOUT_FILTER
LogoutFilter
http/logout
X509_FILTER
X509AuthenticationFilter
http/x509
PRE_AUTH_FILTER
AstractPreAuthenticatedProcessingFilter Subclasses
N/A
CAS_FILTER
CasAuthenticationFilter
N/A
FORM_LOGIN_FILTER
UsernamePasswordAuthenticationFilter
http/form-login
BASIC_AUTH_FILTER
BasicAuthenticationFilter
http/http-basic
SERVLET_API_SUPPORT_FILTER
SecurityContextHolderAwareFilter
http/@servlet-api-provision
REMEMBER_ME_FILTER
RememberMeAuthenticationFilter
http/remember-me
ANONYMOUS_FILTER
AnonymousAuthenticationFilter
http/anonymous
SESSION_MANAGEMENT_FILTER
SessionManagementFilter
session-management
EXCEPTION_TRANSLATION_FILTER
ExceptionTranslationFilter
http
FILTER_SECURITY_INTERCEPTOR
FilterSecurityInterceptor
http
SWITCH_USER_FILTER
SwitchUserFilter
N/A
만약 에 우리 가 해당 하 는 검증 처리 방법 (필터 안에 있 음) 을 스스로 맞 추 려 면 우 리 는 위의 필 터 를 대조 하여 해당 하 는 인터페이스 방법 을 덮어 쓸 수 있다.
제 처리 과정 에 따 르 면 주로 사용자 이름 비밀번호 의 검증 과정 입 니 다. 저 는 자신의 설정 과 처리 과정 을 대체적으로 설명 하 겠 습 니 다.
1. namespace 탭 설정:
<http use-expressions="true" ><!-- This is not the default value -->
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter"/> <!--This is my own filter which just extends AbstractAuthenticationProcessingFilter as what UsernamePasswordAuthenticationFilter does.-->
<intercept-url pattern="/test/**" access="hasRole('ROLE_MY')"/><!-- I tested that what is role,and how I can use it.So ROLE_MY is just a role name I defined.-->
<intercept-url pattern="/login.jsp*" access="permitAll" />
<logout />
<anonymous />
<http-basic />
</http>
문 제 는 필 터 를 맞 추 려 면 < custom - filter / > 를 통 해 표 1 에서 지정 한 position 를 대조 하여 기본 filter 를 덮어 쓰 는 것 입 니 다.
2. 나의 form - login filter 설정 (이 설정 들 은 모두 application - security. xml 파일 에 있 습 니 다) 은:
<beans:bean id="myFilter"
class="com.saveworld.authentication.filters.MyUsernamePasswordAuthenticationFilter">
<beans:property name="defaultTargetUrl" value="/default.jsp" />
<beans:property name="defaultFailureUrl" value="/error.jsp" />
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="filterProcessesUrl" value="/j_spring_security_check" />
<beans:property name="continueChainBeforeSuccessfulAuthentication" value="false" />
</beans:bean>
NOTE:
여기 서 문제 가 있 습 니 다: filter position conflicts!
하면, 만약, 만약...
<http auto-config='true'>
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter"/>
</http>
사용자 정의 filter 에 대응 하 는 position 는 FORMLOGIN_FILTER
그러나 auto - config = 'true' 를 사 용 했 기 때문에 기본적으로 < form - login / >, which is on the position FORM 이 있 습 니 다.LOGIN_FILTER!
이때 position conflicts 문제 가 발생 합 니 다.물론 auto - config = 'true' 를 설정 하지 않 았 다 면 < form - login / > 을 스스로 설정 하 였 습 니 다. 하하, 이 상황 은 자신의 부주의 인지 position conflicts 의 이상 이 있 는 지 잘 보 세 요. 따라서 위의 표 가 상당히 필요 합 니 다. 모든 position 가 기본적으로 namespace 에 대응 하 는 지, 어떤 filter 에 대응 하 는 지 잘 보 세 요!
이어서:
내 클래스 MyUsernamePassword Authentication Filter 구현 (내 설명 방식 은 필요 한 곳, 가입 하 는 방식):
package com.saveworld.authentication.filters;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.NullRememberMeServices;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.util.TextEscapeUtils;
import org.springframework.util.Assert;
import com.saveworld.authentication.handlers.MySavedRequestAwareAuthenticationSuccessHandler;
import com.saveworld.authentication.handlers.MySimpleUrlAuthenticationFailureHandler;
public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter{
//~ Static fields/initializers =====================================================================================
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private boolean postOnly = true;
private boolean allowSessionCreation = true;
private String defaultTargetUrl = "/";
private String defaultFailureUrl = "/login.jsp";
private AuthenticationSuccessHandler successHandler = null;
private AuthenticationFailureHandler failureHandler = null;
private RememberMeServices rememberMeServices = null;
//~ Constructors ===================================================================================================
public MyUsernamePasswordAuthenticationFilter() {
//
super("/j_spring_security_check");
this.rememberMeServices = (super.getRememberMeServices() == null)
? new NullRememberMeServices():super.getRememberMeServices();
}
//~ Methods ========================================================================================================
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Place the last username attempted into HttpSession for views
HttpSession session = request.getSession(false);
if (session != null || getAllowSessionCreation()) {
request.getSession().setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY, TextEscapeUtils.escapeEntities(username));
}
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
public void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
}
SecurityContextHolder.getContext().setAuthentication(authResult);
rememberMeServices.loginSuccess(request, response, authResult);
// Fire event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
}
if(successHandler == null){
successHandler = new MySavedRequestAwareAuthenticationSuccessHandler(getDefaultTargetUrl());
}
successHandler.onAuthenticationSuccess(request, response, authResult);
}
public void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
SecurityContextHolder.clearContext();
if(failureHandler == null){
failureHandler = new MySimpleUrlAuthenticationFailureHandler(getDefaultFailureUrl());
}
if (logger.isDebugEnabled()) {
logger.debug("Authentication request failed: " + failed.toString());
logger.debug("Updated SecurityContextHolder to contain null Authentication");
logger.debug("Delegating to authentication failure handler" + failureHandler);
}
HttpSession session = request.getSession(false);
if (session != null || allowSessionCreation) {
request.getSession().setAttribute(SPRING_SECURITY_LAST_EXCEPTION_KEY, failed);
}
rememberMeServices.loginFail(request, response);
failureHandler.onAuthenticationFailure(request, response, failed);
}
/**
* Enables subclasses to override the composition of the password, such as by including additional values
* and a separator.<p>This might be used for example if a postcode/zipcode was required in addition to the
* password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The
* <code>AuthenticationDao</code> will need to generate the expected password in a corresponding manner.</p>
*
* @param request so that request attributes can be retrieved
*
* @return the password that will be presented in the <code>Authentication</code> request token to the
* <code>AuthenticationManager</code>
*/
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
/**
* Enables subclasses to override the composition of the username, such as by including additional values
* and a separator.
*
* @param request so that request attributes can be retrieved
*
* @return the username that will be presented in the <code>Authentication</code> request token to the
* <code>AuthenticationManager</code>
*/
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
/**
* Provided so that subclasses may configure what is put into the authentication request's details
* property.
*
* @param request that an authentication request is being created for
* @param authRequest the authentication request object that should have its details set
*/
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
/**
* Sets the parameter name which will be used to obtain the username from the login request.
*
* @param usernameParameter the parameter name. Defaults to "j_username".
*/
public void setUsernameParameter(String usernameParameter) {
Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
this.usernameParameter = usernameParameter;
}
/**
* Sets the parameter name which will be used to obtain the password from the login request..
*
* @param passwordParameter the parameter name. Defaults to "j_password".
*/
public void setPasswordParameter(String passwordParameter) {
Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
this.passwordParameter = passwordParameter;
}
/**
* Defines whether only HTTP POST requests will be allowed by this filter.
* If set to true, and an authentication request is received which is not a POST request, an exception will
* be raised immediately and authentication will not be attempted. The <tt>unsuccessfulAuthentication()</tt> method
* will be called as if handling a failed authentication.
* <p>
* Defaults to <tt>true</tt> but may be overridden by subclasses.
*/
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public final String getUsernameParameter() {
return usernameParameter;
}
public final String getPasswordParameter() {
return passwordParameter;
}
public String getDefaultTargetUrl() {
return defaultTargetUrl;
}
public void setDefaultTargetUrl(String defaultTargetUrl) {
this.defaultTargetUrl = defaultTargetUrl;
}
public String getDefaultFailureUrl() {
return defaultFailureUrl;
}
public void setDefaultFailureUrl(String defaultFailureUrl) {
this.defaultFailureUrl = defaultFailureUrl;
}
}
여기 서 주목 해 야 할 것 은 몇 개의 필드 입 니 다.
이 두 필드 는 인증 이 성공 하거나 실 패 했 을 때 방향 을 바 꾸 는 페이지 입 니 다. "/" 로 시작 하 는 것 을 주의해 야 합 니 다. 그렇지 않 으 면 Abstract Authentication TargetUrl RequestHandler 에서 set Default TargetUrl 방법 을 호출 할 때 "default Target must start with '/' or with 'http (s)' 의 이상 을 던 집 니 다!
기본적으로 FORMLOGIN_FILTER 에 대응 하 는 target url 과 failure url 은 모두 < form - login / > 을 통 해 이 루어 집 니 다.
default - target - url, authentication - failure - url 지정, authentication - success - handler - ref 와 authentication - failure - handler - ref 를 지정 하여 인증 성공 과 실패 후의 처리 방식 을 실현 할 수 있 습 니 다. 제 filter 에 서 는 두 개의 handler 가 각각 성공 과 실패 에 대응 하 는 인증 을 사용자 정의 하 였 습 니 다.
3. 사용자 정보 획득 과 검증:
이 지정 한 authentication - manager 는 기본 Provider Manager 를 사용 합 니 다. 이 관리 자 는 어디에서 사용 합 니까?
MyUsernamePassword AuthenticationFilter 의 attempty Authentication 방법의 마지막 줄 을 보십시오. 지정 한 authentication - manager 를 가 져 옵 니 다.getAuthenticationManager 는 부모 클래스 Abstract AuthenticationProcessingFilter 에서 물 려 받 았 습 니 다.따라서 우리 의 < authentication - manager alias = "authentication Manager" > 에 별명 authentication Manager 가 지정 되 어 있 습 니 다. my filter 에 속성 을 설정 한 참조 < beans: property name = "authentication Manager" ref = "authentication Manager" / > 를 참조 한 다음 Provider 를 통 해 사용자 정 보 를 참조 하여 서 비 스 를 검증 할 수 있 습 니 다.(eg: 사용자 정보 획득 과 검증)! 이 곳 은 실제 Method Template 모드 를 사 용 했 습 니 다 (Abstract AuthenticationManager 에서 템 플 릿 함수 doAuthentication 을 설정 하고 Provider Manager 에서 이 루어 졌 습 니 다).
여기 서 우리 의 서비스 가 어떻게 호출 되 었 는 지 설명 하기 어렵 습 니 다. 우 리 는 < authentication - provider user - service - ref = 'my UserDetails Service' / > 를 설정 하 였 습 니 다.
우리 의 UserDetailsService, 클래스 구현 (테스트 와 이 해 를 위해 The easier the better!) 을 지정 하 였 습 니 다.
package com.saveworld.userdetails;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
public class MyUserDetailsService implements UserDetailsService{
private HashMap<String, User> userDetails = new HashMap<String, User>();
private HashMap<String, List<GrantedAuthority>> userAuthorities = new HashMap<String, List<GrantedAuthority>>();
public MyUserDetailsService(){
//Make up a user named 'rod' with 'rod' as his password!
//
String username = "rod";
String password = "1";
boolean enabled = true;
//purview for rod
GrantedAuthority specAuth = new GrantedAuthorityImpl("ROLE_MY");
List<GrantedAuthority> rodsAuthsList = new ArrayList<GrantedAuthority>();
rodsAuthsList.add(specAuth);
// userAuthorities.put("rod", rodsAuthsList);
userDetails.put("rod", new User(username, password, enabled, true, true, true, rodsAuthsList));
}
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
System.out.println(" ");
return userDetails.get(username);
}
}
Dao AuthenticationProvider 의 userDetailsService 를 통 해 우리 의 UserDetailsService 와 연 결 됩 니 다.(어 쩔 수 없 이 AbstractUserDetails AuthenticationProvider 에 템 플 릿 함수 retrieveUser 가 설정 되 어 있 고, Dao AuthenticationProvider 가 구현 되 었 으 며, retrieveUser 방법 으로 UserDetails Service. loadUserByUsername 을 호출 한 후, AbstractUserDetails AuthenticationProvider. authenticate 방법 으로 검증 되 었 습 니 다).
다음은 검증 결과 입 니 다. 성공 여 부 를 보고 filter chain 에 들 어 갑 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[Spring] Spring Security - JWT강력한 사용자 인증 및 Access 제어 framework이다. 이는 Java 애플리케이션에 인증 및 권한 부여를 제공하는데 중점을 두었으며 다양한 필터를 사용하여 커스터마이징이 가능하다. '인증(Authentica...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.