SpringSecurity3.2.10 + SpringBoot2.1.11+ConcurrentSession(分散セッション)+redis
32584 ワード
注意:SpringBoot 2.1.11より高いバージョンのSpringSecurityを組み合わせるべきです.
1、maven依存を導入する
本プロジェクトで使用するSpringBoot 2.1.11では、付属のspring-boot-starter-securityバージョンを導入して5.1.7となっていますが、古いプロジェクトで古いバージョンと互換性が必要なため、低バージョンの3つのSpringSecurityパッケージを使用しています.
マルチノード分散配置を適用する場合、SpringSecurity自体は分散セッションを制御できないため、サードパーティ製メディアの介入が必要です.ここでredisを選択し、redis依存をインポートします.
2、カスタム分散セッション制御クラス
ここではまずコードを貼って、後でSpringBootとSpringSecurityにどのように注入するかを話します.
3、MySessionRegistryImpl SpringBoot注入SpringSecurity
このセクションでは、低バージョンのSpringSecurityを使用しているので、spring公式サイトのアドレスを参照してください.https://docs.spring.io/spring-security/site/docs/3.1.x/reference/session-mgmt.html 《12. Session Management Prev Part III. Web Application Security》
SpringSecurityのその他の高バージョンの公式ドキュメントアドレス参照:https://docs.spring.io/spring-security/site/docs/
4、SecurityContextHolderではなく、Sessionからlogin userを取得する.getContext().getAuthentication()ここでログインユーザを取得
このお兄さんに感謝します.http://www.manongjc.com/article/97630.html『SecurityContextHolder.getContext().getAuthentication()がnullの場合』
原理の説明:
SpringSecurityに複数のFilterフィルタチェーンを定義しても、最後にSpringSecurityはSecurityContextHolderを実行します.clearContext(); また、SecurityContextHolderを空にすることで、SecurityContextHolderが得られる.getContext().getAuthentication()=nullの場合.
したがって、現在のユーザを取得するにはspring securityフィルタ実行でlogin userを取得する方法を実行する必要があります.
マイソリューション:
ここではMySessionRegistryImplカスタム分散セッションコントローラにlogin userをredisに格納することを選択します.
バックグラウンドログインフィルタLogonFilterを定義し、任意のControllerリクエストに到達する前にredisのlogin userを取得してsessionに配置し、springコンテナはspring-session-data-redis依存性を導入したため、redisを通じてsessionをredisに接続されたすべてのSpringBootノードに同期した.
5、requestを取得するコツ
end.
1、maven依存を導入する
本プロジェクトで使用するSpringBoot 2.1.11では、付属のspring-boot-starter-securityバージョンを導入して5.1.7となっていますが、古いプロジェクトで古いバージョンと互換性が必要なため、低バージョンの3つのSpringSecurityパッケージを使用しています.
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-coreartifactId>
<version>3.2.10.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-webartifactId>
<version>3.2.10.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-configartifactId>
<version>3.2.10.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-coreartifactId>
exclusion>
<exclusion>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-webartifactId>
exclusion>
<exclusion>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-configartifactId>
exclusion>
exclusions>
dependency>
マルチノード分散配置を適用する場合、SpringSecurity自体は分散セッションを制御できないため、サードパーティ製メディアの介入が必要です.ここでredisを選択し、redis依存をインポートします.
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
<version>1.5.22.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.sessiongroupId>
<artifactId>spring-session-data-redisartifactId>
dependency>
2、カスタム分散セッション制御クラス
ここではまずコードを貼って、後でSpringBootとSpringSecurityにどのように注入するかを話します.
import com.test.MyUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.session.SessionDestroyedEvent;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
@Component
public class MySessionRegistryImpl implements SessionRegistry, ApplicationListener {
private static final Logger logger = LoggerFactory.getLogger(MySessionRegistryImpl.class);
// , Spring : org.springframework.security.core.session.SessionRegistryImpl
/** */
private final ConcurrentMap
3、MySessionRegistryImpl SpringBoot注入SpringSecurity
このセクションでは、低バージョンのSpringSecurityを使用しているので、spring公式サイトのアドレスを参照してください.https://docs.spring.io/spring-security/site/docs/3.1.x/reference/session-mgmt.html 《12. Session Management Prev Part III. Web Application Security》
SpringSecurityのその他の高バージョンの公式ドキュメントアドレス参照:https://docs.spring.io/spring-security/site/docs/
@Autowired
MySessionRegistryImpl mySessionRegistryImpl; //
@Bean("concurrentSessionControlStrategy")
public org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy getConcurrentSessionControlStrategy(){
return new ConcurrentSessionControlStrategy(mySessionRegistryImpl); // ,ConcurrentSessionControlStrategy SpringSecurity 3.2.10
}
@Bean("authenticationFilter")
public MyAuthenticationFilter getMyAuthenticationFilter(
@Qualifier("authenticationManager") ProviderManager authenticationManager
,@Qualifier("successHandler") MyAuthenticationSuccessHandler successHandler
,@Qualifier("failureHandler") MyAuthenticationFailureHandler failureHandler
,@Qualifier("concurrentSessionControlStrategy") ConcurrentSessionControlStrategy concurrentSessionControlStrategy
){
MyAuthenticationFilter filter = new MyAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager); // spring org.springframework.security.authentication.ProviderManager
filter.setAuthenticationSuccessHandler(successHandler); // extends org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler
filter.setAuthenticationFailureHandler(failureHandler); // implements org.springframework.security.web.authentication.AuthenticationFailureHandler
filter.setFilterProcessesUrl("/login/loginUser.xhtml");
filter.setAllowSessionCreation(false);
// SpringSecurity + SpringBoot + ConcurrentSession + redis
// refer doc from https://docs.spring.io/spring-security/site/docs/3.1.x/reference/session-mgmt.html
filter.setSessionAuthenticationStrategy(concurrentSessionControlStrategy); // !!! session SpringSecurity
return filter;
}
@Bean("securityFilter")
public FilterChainProxy getFilterChainProxy(
@Qualifier("securityContextPersistenceFilter") SecurityContextPersistenceFilter securityContextPersistenceFilter
,@Qualifier("logoutFilter") LogoutFilter logoutFilter
,@Qualifier("authenticationFilter") MyAuthenticationFilter authenticationFilter
,@Qualifier("securityContextHolderAwareRequestFilter") SecurityContextHolderAwareRequestFilter securityContextHolderAwareRequestFilter
,@Qualifier("exceptionTranslationFilter") ExceptionTranslationFilter exceptionTranslationFilter
,@Qualifier("concurrentSessionFilter") ConcurrentSessionFilter concurrentSessionFilter
){
PrefixUriRequestMatcher requestMatcher = new PrefixUriRequestMatcher();
requestMatcher.setPrefixUris("/admin-portal/,/xxxx/");
SecurityFilterChain filterChain = new DefaultSecurityFilterChain(
requestMatcher
,securityContextPersistenceFilter // spring org.springframework.security.web.context.SecurityContextPersistenceFilter
,logoutFilter // spring org.springframework.security.web.authentication.logout.LogoutFilter
,authenticationFilter // extends org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter, implements org.springframework.context.ApplicationContextAware
,securityContextHolderAwareRequestFilter // spring org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
,exceptionTranslationFilter // spring org.springframework.security.web.access.ExceptionTranslationFilter
,concurrentSessionFilter // !!! session ,SpringSecurity Filter
);
FilterChainProxy proxy = new FilterChainProxy(filterChain);
return proxy;
}
4、SecurityContextHolderではなく、Sessionからlogin userを取得する.getContext().getAuthentication()ここでログインユーザを取得
このお兄さんに感謝します.http://www.manongjc.com/article/97630.html『SecurityContextHolder.getContext().getAuthentication()がnullの場合』
原理の説明:
SpringSecurityに複数のFilterフィルタチェーンを定義しても、最後にSpringSecurityはSecurityContextHolderを実行します.clearContext(); また、SecurityContextHolderを空にすることで、SecurityContextHolderが得られる.getContext().getAuthentication()=nullの場合.
したがって、現在のユーザを取得するにはspring securityフィルタ実行でlogin userを取得する方法を実行する必要があります.
マイソリューション:
ここではMySessionRegistryImplカスタム分散セッションコントローラにlogin userをredisに格納することを選択します.
バックグラウンドログインフィルタLogonFilterを定義し、任意のControllerリクエストに到達する前にredisのlogin userを取得してsessionに配置し、springコンテナはspring-session-data-redis依存性を導入したため、redisを通じてsessionをredisに接続されたすべてのSpringBootノードに同期した.
5、requestを取得するコツ
org.springframework.web.context.request.ServletRequestAttributes holder = (ServletRequestAttributes) org.springframework.web.context.request.RequestContextHolder;
javax.servlet.http.HttpServletRequest request = holder.getRequest();
javax.servlet.http.HttpSession session = request.getSession();
end.