起源
標準のRABCでは、権限は動的構成をサポートする必要があり、Spring Securityはコードのアクセス許可に同意するようにデフォルトです。実際のビジネスシナリオでは、通常、ロールアクセス許可を動的に構成すること、つまり実行時にURLに対応するアクセスロールを構成する必要があります。
Spring Securityに基づいて、この要件を達成する方法は?
最も簡単な方法は、フィルターをカスタマイズして許可判決を完了することですが、これはSpring Security Frameworkから分離されています。 Spring Securityに基づいてエレガントに実装する方法は?
Spring Security Authorizationレビュー
Spring Security FilterChainProxyは、Webに登録するフィルターとして使用されます。 FilterChainProxyには、複数の組み込みフィルターが一度に含まれています。まず、Spring Securityに組み込まれたさまざまなフィルターを理解する必要があります。
| エイリアス | フィルタークラス | 名前空間要素または属性 |
|---|---|---|
| Channel_filter | ChannelProcessingFilter | http/intercept-url@reques-channel |
| security_context_filter | SecurityContextPersistenceFilter | http |
| concurrent_session_filter | concurrentsessionfilter | セッション管理/並行性制御 |
| headers_filter | HeaderWriterFilter | HTTP/ヘッダー |
| csrf_filter | csrffilter | http/csrf |
| logout_filter | logoutfilter | http/logout |
| x509_filter | x509AuthenticationFilter | HTTP/X509 |
| pre_auth_filter | AbstractPreauthenticatedProcessingFilterサブクラス | 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 | securitycontextholderawarequestfilter | http/@servlet-api-provision |
| jaas_api_support_filter | JaasapiintegrationFilter | http/@jaas-api-provision |
| remember_me_filter | rememberMeauthenticationFilter | http/remember-me |
| anonymous_filter | anonymousauthenticationfilter | http/匿名 |
| session_management_filter | SessionManagementFilter | セッション管理 |
| Exception_translation_filter | ExceptionTranslationFilter | http |
| filter_security_interceptor | filtersecurityInterceptor | http |
| switch_user_filter | switchuserfilter | n/a |
最も重要なことは、主な認証ロジックを実装するFiltersecurityInterceptorであり、最もコアコードはここにあります。
Inclocation(Object object){// URL Collection <ConfigAttribute>属性にアクセスするために必要な権限を取得してください。 Authentication Authentivated = AuthenticateIfRequired(); // AccessDecisionManagerを介した認証try {this.accessdecisionmanager.docide(認証、オブジェクト、属性); } catch(AccessDenIedException AccessDenIedException){publishevent(new AutherizationFailureEvent(Object、属性、認証、AccessDeneDException)); AccessDenIedExceptionを投げます。 } if(debug){logger.debug( "承認成功"); } if(publishauthorizationsuccessful ");} if(publishauthorizationsucess){publishevent(new authorizevent(object、actrubutes、actunticated));} //別のユーザー認証runasとして実行しようとします。 logger.debug(runasmanagerは認証オブジェクトを変更しませんでした} SecurityContexTholder.setContext(SecurityContholder.getContext();上記からわかるように、動的認証を実現するために、2つの側面から始めることができます。
個別に実装する方法を見てみましょう。
カスタムAccessDecisionManager
3つの公式AccessDecisionManagersはすべてAccessDecisionVoterに基づいて許可認証を実装するため、AccessDecisionVoterをカスタマイズするだけです。
カスタマイズは、主にAccessDecisionVoterインターフェイスを実装します。公式のロレボーターをフォローすることができます。
Public Class RoleBasedVoterはAccessDecisionVoter <Object> {@Override public Boolean Supports(configAttribute attribute){return true; } @override public int bote(authentication authentication、object object、collection <configattribute> attributes){if(authentication == null){return Access_denied; } int result = access_abstain;コレクション<?拡張authedauthority>当局=抽出(認証); for(configAttribute attribute:attributes){if(attribute.getAttribute()== null){継続; } if(this.supports(属性)){result = access_denied; //(付与承認権限:当局)のマッチング許可当局を見つけようとします{if(astribute.getAttribute()。 }}}} return result; } collection <?拡張補助金> extractauthorities(authentication authentication){return authentication.getauthorities(); } @Override public boolean supports(class clazz){return true; }}動的権限を追加する方法は?
vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes)はFilterInvocationであり、GetRequesturlを使用して現在の要求のURLを取得できます。
filterInvocation fi =(filterInvocation)オブジェクト; string url = fi.getRequesturl();
したがって、ここには拡張の余地がたくさんあります。 DBから動的にロードしてから、URLのconfigAttributeを判断できます。
このロールベースVoterの使用方法は? AccessDecisionManagerメソッドを使用して、構成でカスタマイズします。公式の全会一致を使用してから、カスタマイズされたロールベースVoterを追加する必要があります。
@enablewebsecurity @enableglobalmethodsecurity(prepostenabled = true、securedenabled = true)public class contoconfiguration extends extends websecurityconfigureradapter {@override保護されたvoid configure(httpsecurity http)スロー例外{http .addfilterfore(corsefiltertersedamepass) .exceptionHandling().AuthENTICENTENTRYPOINT(sextureSupport).AccessDeniedHandler(resultsupport).and().csrf().disable().frameoptions().disable().and().sessionmanagemen .authorizerequests()// custom AccessDecisionManager .AccessDecisionManager(AccessDecisionManager()).and().Apply(SecurityConfigurerAdapter()); } @bean public AccessDecisionManager AccessDecisionManager(){list <AccessDecisionVoter <? object >> decisionVoters = arrays.Aslist(new WebExpressionVoter()、// new Rolevoter()、new RoleBasedVoter()、new AuthenticedVoter());新しいunimousbased(decisionvoters)を返します。 }SecurityMetadataSourceをカスタマイズします
カスタムFilterInvocationseCurityMetadataSourceは、インターフェイスを実装するだけで、インターフェイスのDBからルールを動的にロードする必要があります。
コードの定義を再利用するために、コードで生成されたSecurityMetadataSourceを取得し、コンストラクターのデフォルトのfilterInvocationsecurityMetadataSourceで渡すことができます。
パブリッククラスappfilterinvocationsecuritymetadatasourceはorg.springframework.security.web.access.intercept.filterinvocationsecuritymetadatasource {private filter invocationsecuritymetadatasource supermetadatasource; @override public collection <configattribute> getallconfigattributes(){return null; } public appfilterinvocationsecuritymetadatasource(filterinvocationsecuritymetadatasource expressionbasedfilterinvocationsecuritymetadatasource){this.supermetadatasource = expression -basedfilterinvocationsecuritymetadatasource; //データベースからのTODOロード許可構成//ここでは、プライベート最終マップ<文字列> urlrolemap = new hashmap <string、string>(){{put( "/open/**"、 "chole_anonymous"); put( "/health"、 "role_anonymous"); put( "/restart"、 "chole_admin"); put( "/demo"、 "chole_user"); }}; @Override public collection <configattribute> getattributes(object object)throws IllegalargumentException {filterInvocation fi =(filterInvocation)object; string url = fi.getRequesturl(); for(map.entry <string、string> entry:urlrolemap.entryset()){if(antpathmatcher.match(entry.getKey()、url)){return securityconfig.createList(entry.getValue()); }} //コードで定義されたデフォルトの構成を返すsupermetadatasource.getattributes(object); } @Override public boolean supports(class <?> clazz){return filterInvocation.class.isassignablefrom(clazz); }}それを使用する方法は? AccessDecisionManagerとは異なり、ExpressionUrthorizationConfigurerは、FiltersecurityInterceptorのfilterinvocationsecuritymetadataSourceを設定するための設定された方法を提供しません。
ObjectPostProcessorを使用して拡張メソッドを検索します。これにより、FiltersecurityInterceptorタイプを処理するObjectPostProcessorをカスタマイズして、FiltersecurityInterceptorを変更できます。
@enablewebsecurity @enableglobalmethodsecurity(prepostenabled = true、securedenabled = true)public class contoconfiguration extends extends websecurityconfigureradapter {@override保護されたvoid configure(httpsecurity http)スロー例外{http .addfilterfore(corsefiltertersedamepass) .exceptionHandling().AuthENTICENTENTRYPOINT(sextureSupport).AccessDeniedHandler(resultsupport).and().csrf().disable().frameoptions().disable().and().sessionmanagemen .authorizerequests()// custom filterinvocationsecuritymetadatasource .withobjectpostprocessor(new objectPostProcessor <FilterSecurityInterceptor>(){@Override public <o extends filtersecurityinterceptor> o postprocess(o fsi){ fsi.setsecuritymetadatasource(mysecuritymetadatasource(fsi.getsecuritymetadatasource()))。 } @bean public appfilterinvocationsecuritymetadatasource mysecuritymetadatasource(filterinvocationsecuritymetadatasource filterinvocationsecuritymetadatasource){appfilterinvocationsecuritymetadatasource securitymetadatasource = new appfilterinvocationsecuritymetadatasource(filterinvocationsecuritymetadatasource); SecurityMetadataSourceを返します;}まとめ
この記事では、Spring Securityに基づいて動的権限を実装する2つの方法を紹介します。 1つはAccessDecisionManagerをカスタマイズすることであり、もう1つはFilterInvocationsecurityMetadataSourceをカスタマイズすることです。実際のプロジェクトのニーズに応じて柔軟に選択できます。
さらに読む:
スプリングセキュリティアーキテクチャとソースコード分析
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。