0

Springセキュリティ(2.0.x)http名前空間、フォームログイン定義は自動的にAuthenticationProcessingFilterを使用します。

<form-login login-page='/logon.jsp' 
default-target-url='/home.jsp' 
always-use-default-target='true' />

auto-config="false"また、設定すると、カスタムBean定義を提供することで認証をカスタマイズできることも知っています。

AuthenticationProcessingFilterを拡張するCustomAuthenticationProcessingFilterがgetUsernameをオーバーライドし、カスタムロジックを使用して渡されたものよりもユーザー名を取得します。

protected String obtainUsername(HttpServletRequest request) {
   // custom logic to return username from parameter/cookies/header etc ... 
}

auto-config="true" <form-login>customAuthFilterとすべての依存Beanを定義する必要なしに、使用しながらCustomAuthenticationProcessingFilterを使用することは可能ですか?

  <beans:bean id="customAuthFilter" class="x.y.z.CustomAuthenticationProcessingFilter">
    <custom-filter  position="AUTHENTICATION_PROCESSING_FILTER" />
    <beans:property name="defaultTargetUrl" value="/home.jsp"></beans:property>
    ...
    ...
  </beans:bean>
4

3 に答える 3

1

はじめに

Spring Security 2.0 はメンテナンス モードであるため、正式な更新は行われません。ただし、この問題を回避するために使用できるアプローチがいくつかあります。

BeanPostProcessor

Spring Security FAQから使用できるトリックは、BeanPostProcessor を使用することです。プロパティを変更する代わりに、カスタム フィルターを返すことができます。例は次のようになります。

public class CustomFilterBeanPostProcessor implements BeanPostProcessor {
    private Filter customFilter;

    public Object postProcessAfterInitialization(Object bean, String name) {
        if (bean instanceof AuthenticationProcessingFilter) {
           return customFilter;
        }
        return bean;
    }

    public Object postProcessBeforeInitialization(Object bean, String name) {
        return bean;
    }

    public void setFilter(Filter filter) {
        this.customFilter = filter;
    }
}

次に、構成には次のものが含まれます。

  <beans:bean class="CustomFilterBeanPostProcessor">
    <beans:property name="filter" ref="customAuthFilter"/>
  </beans:bean>

属性の前に使用

別の方法として、AuthenticationProcessingFilter の前にカスタム フィルターを挿入する方法があります。これには追加のフィルターがありますが、これは小さく、到達するべきではないため (つまり、AuthenticationProcessingFilter が要求を無視する場合にのみカスタム フィルターが FilterChain を継続するため)、最小限の侵襲性である必要があります。このアプローチを使用した構成例を以下に示します。

<beans:bean id="customAuthFilter" class="x.y.z.CustomAuthenticationProcessingFilter">
    <custom-filter before="AUTHENTICATION_PROCESSING_FILTER" />
    <beans:property name="defaultTargetUrl" value="/home.jsp"></beans:property>
    ...
    ...
  </beans:bean>
于 2012-09-05T19:38:42.220 に答える
0

残念ながら、見た目どおり(私が間違っていなければ)、AuthenticationProcessingFilterクラス名は< HttpSecurityBeanDefinitionParser> :(にハードコーディングされているため、何もできませんでした。

if (formLoginElt != null || autoConfig) {
  FormLoginBeanDefinitionParser parser = 
     new FormLoginBeanDefinitionParser("/j_spring_security_check", 
     "org.springframework.security.ui.webapp.AuthenticationProcessingFilter");

フィルタクラスが構成属性であり、(のようにdefault-target-url)外部で制御されて属性を使用している場合は、より適切でした。authentication-filter-class

<form-login login-page='/logon.jsp' 
default-target-url='/home.jsp' 
always-use-default-target='true'
authentication-filter-class='x.y.z.CustomAuthenticationProcessingFilter'
/>

春の人々が聞いていることを願っています;)

于 2012-09-04T16:55:03.097 に答える
0

実際のところ、Spring の名前空間ハンドラーは_formLoginFilter、AuthenticationProcessingFilter の名前で Bean を内部的に定義しています ( BeanIdsの完全なリストについては、を参照してください)。この問題を回避する方法はいくつかあります (つまり、 DaoAuthenticationProvider から j_username 以外のものを使用して認証する、ヘッダーからユーザー名を取得するなど...)。

Spring AOPbean()構文を使用してインターセプトするdoFilter()

_formLoginFilter名前とインターセプトdoFilterメソッドで Bean を探すポイントカットを定義します。( AuthenticationProcessingFilter.doFilter() method) 条件付きで別のものに委任する

public class AuthenticationProcessingFilterAspect {
  private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationProcessingFilterAspect.class);
  public Object intercept(ProceedingJoinPoint pjp) throws Throwable {
    LOGGER.info("intercept------------------{}",pjp.toLongString());
    //Delegate to customised method instead of default  pjp.proceed()
    return pjp.proceed();
  }
}

設定

<beans:bean id="authFilterAspect" class="x.y.z.AuthenticationProcessingFilterAspect" />
<aop:config>
  <aop:aspect ref="authFilterAspect">
    <aop:around pointcut="bean(_formLoginFilter) &amp;&amp; execution(* doFilter(..))" method="intercept"/>
  </aop:aspect>
</aop:config>

CustomWebAuthenticationDetails を使用して認証を行う

カスタムフィールドに入力する CustomWebAuthenticationDetails を注入する AuthenticationProcessingFilter Bean の Bean ポストプロセッサーを定義します

public class AuthenticationProcessingFilterBeanPostProcessor implements
    BeanPostProcessor {

  private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationProcessingFilterBeanPostProcessor.class);

  public Object postProcessAfterInitialization(Object bean, String beanName)
      throws BeansException {
    if ("_formLoginFilter".equals(beanName) && bean instanceof AuthenticationProcessingFilter) {
      AuthenticationProcessingFilter filter = (AuthenticationProcessingFilter) bean;
      WebAuthenticationDetailsSource source = (WebAuthenticationDetailsSource) filter.getAuthenticationDetailsSource();
      source.setClazz(CustomWebAuthenticationDetails.class);
    }
    return bean;
  }

  public Object postProcessBeforeInitialization(Object bean, String beanName)
      throws BeansException {
    return bean;
  }

  @SuppressWarnings("serial")
  public static class CustomWebAuthenticationDetails extends
      WebAuthenticationDetails {
    private String customAttribute;//customfield
    public CustomWebAuthenticationDetails(HttpServletRequest request) {
      super(request);
      //Build custom attributes that could be used elsewhere (say in DaoAuthenticationProvider ) 
      //with (CustomWebAuthenticationDetails)authentication.getDetails()
      customAttribute = request.getHeader("username");
    }
    public boolean getCustomAttribute() {
      return customAttribute;
    }
  }
}

設定

<beans:bean id="authFilterProcessor" class="x.y.z.AuthenticationProcessingFilterBeanPostProcessor" />

スレッド バインド リクエストを使用して実際の認証を行う (DaoAuthenticationProvider 内)

getHttpServletRequest() を使用してスレッドバインドされたリクエスト オブジェクトにアクセスし、request.getHeader("username") を使用してカスタム認証を行います。

public static HttpServletRequest getHttpServletRequest(){
  return((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
}

また、リクエストが DispatcherServlet を介していない場合は、web.xml でこれを定義する必要があります。

<filter>
  <filter-name>requestContextFilter</filter-name>
  <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>requestContextFilter</filter-name>
  <url-pattern>/j_spring_security_check</url-pattern>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
  <filter-name>requestContextFilter</filter-name>
  <url-pattern>/j_spring_security_logout</url-pattern>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>REQUEST</dispatcher>
</filter-mapping>

その顔のアプリケーションを使用する場合FacesContext.getCurrentInstance()

public static HttpServletRequest getHttpServletRequest(){
    FacesContext context = FacesContext.getCurrentInstance();
    return (HttpServletRequest) context.getExternalContext().getRequest();
}
于 2012-09-10T17:18:32.087 に答える