2

Spring MVCを使用していますが、ユーザーの試用期間が終了しているかどうかを確認したいと思います。

次の方法でSpringSecurityを使用してユーザーの詳細を取得しています

  public User getUserDetail() {
    Authentication auth = SecurityContextHolder.getContext()
            .getAuthentication();   
    Object principal = auth.getPrincipal();
        if(principal instanceof User){
            User user = (User) principal;               
            return user;
        }
        return null;
}

ユーザーオブジェクトには、最初にログインした日付が含まれています。

次のコードを使用してユーザーサブスクリプションを確認しています

   UserBean userLoggedIn = (UserBean) userService.getUserDetail();

    Date dt =  userLoggedIn.getUserCreationDate();

    DateTime userCreated =  new DateTime(dt).plusDays(TRIAL_PERIOD);

    DateTime currentDateTime = new DateTime();


    if(currentDateTime.compareTo(userCreated) > 0 && userLoggedIn.getPackageType() == 0){
        return new ModelAndView("pricing","user",userLoggedIn);
    }

今の私の問題は、各コントローラーで上記のコードを繰り返し書きたくないということです。それで、ユーザーの試用期間が満了するかどうかを確認して、価格設定ページにリダイレクトできる一般的な場所はありますか?

データベースからユーザーの詳細にアクセスし、Springセキュリティセッションに配置するCustomUserDetailクラスがあります。したがって、ユーザーの試用期間が終了しているかどうかを確認するのに最適な場所だと思いますが、このクラスから価格設定ページにユーザーをリダイレクトする方法がわかりません。

私のCustomUserDetailクラスは

  @Service
  @Transactional(readOnly = true)
 public class CustomUserDetailsService implements UserDetailsService {

static final Logger logger = Logger.getLogger(CustomUserDetailsService.class);


@Resource(name="userService")
private UserService userService;

/* (non-Javadoc)
 * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
 */
@Override
public UserDetails loadUserByUsername(String email)
        throws UsernameNotFoundException, DataAccessException {
        try {

            boolean enabled = true;
            boolean accountNonExpired = true;
            boolean credentialsNonExpired = true;
            boolean accountNonLocked = true;

            UserBean domainUser = userService.getUserByName(email);     

            domainUser.isEnabled();
            domainUser.isAccountNonExpired();
            domainUser.isCredentialsNonExpired();
            domainUser.isAccountNonLocked();


    //Collection<? extends GrantedAuthority> roles =  getAuthorities((long) domainUser.getRoleId());

    return domainUser;


    } catch (Exception e) {
        logger.error("Invalid Login.",e);
        throw new RuntimeException(e);
    }
}

- -更新しました - -

私のspring-security.xmlは

    <form-login login-page="/login.htm" 
                authentication-failure-url="/loginfailed.htm"
                authentication-failure-handler-ref="exceptionMapper"
                default-target-url="/index.htm" 
                always-use-default-target="true"/>

    <access-denied-handler error-page="/logout.htm"/>

    <logout invalidate-session="true" 
        logout-url="/logout.htm"
        success-handler-ref="userController"/>
 <remember-me user-service-ref="customUserDetailsService" key="89dqj219dn910lsAc12" use-secure-cookie="true"  token-validity-seconds="466560000"/>
 <session-management session-authentication-strategy-ref="sas"/>
</http>

<authentication-manager>
        <authentication-provider user-service-ref="customUserDetailsService">
                <password-encoder ref="customEnocdePassword" >
                    <salt-source user-property="email"/>
                </password-encoder>
        </authentication-provider>
</authentication-manager>   
<beans:bean id="customEnocdePassword" class="com.mycom.myproj.utility.CustomEnocdePassword" />

<beans:bean id="exceptionMapper" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler" >
<beans:property name="exceptionMappings">
    <beans:map>
        <beans:entry key="your.package.TrialPeriodExpiredException" value="/pricing"/>
    </beans:map>
</beans:property>
</beans:bean>

<beans:bean id="sas"
  class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="maximumSessions" value="3" />

- -アップデート - -

今私がしたことは

 <beans:bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <beans:property name="userDetailsService" ref="customUserDetailsService"/>
    <beans:property name="passwordEncoder" ref="customEnocdePassword"/>
    <beans:property name="preAuthenticationChecks" ref="expirationChecker"/>
</beans:bean>

<authentication-manager>
    <authentication-provider user-service-ref="authenticationProvider">
        <password-encoder ref="customEnocdePassword" >
               <salt-source user-property="email"/>
        </password-encoder>
    </authentication-provider>
</authentication-manager>

<!-- <authentication-manager>
        <authentication-provider user-service-ref="customUserDetailsService">
                <password-encoder ref="customEnocdePassword" >
                    <salt-source user-property="email"/>
                </password-encoder>
        </authentication-provider>
</authentication-manager> -->
<beans:bean id="expirationChecker" class="com.mycom.myproj.utility.UserTrialPeriodExpirationChecker" />
<beans:bean id="customEnocdePassword" class="com.mycom.myproj.utility.CustomEnocdePassword" />

今、私はエラーを下回っています

 "Cannot convert value of type [org.springframework.security.authentication.dao.DaoAuthenticationProvider]
to required type [org.springframework.security.core.userdetails.UserDetailsService] 
for property 'userDetailsService': no matching editors or conversion strategy found"
4

1 に答える 1

3

ユーザーを認証する前に有効期限を確認するカスタムUserDetailsCheckerを に設定できます。DaoAuthenticationProvider

構成内の<authentication-provider>要素は を生成しますが、その要素には、そのプロパティDaoAuthenticationProviderを設定できる属性がありません。preAuthenticationChecks名前空間構成のこの制限を回避するには、そのプロバイダーを通常の Bean として定義するようにフォールバックする必要があります。

<bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <property name="userDetailsService" ref="customUserDetailsService"/>
    <property name="passwordEncoder" ref="customEnocdePassword"/>
    <property name="preAuthenticationChecks" ref="expirationChecker"/>
</bean>

構成内の id で参照します<authentication-manager>

<security:authentication-manager>
    <security:authentication-provider ref="authenticationProvider"/>
</security:authentication-manager>

上記のBeanは、オブジェクトを受け取るコールバック インターフェイスをexpirationChecker実装する必要があり、ユーザーの試用期間が終了した場合に特定の例外をスローできます。UserDetailsCheckerUserDetails

public class UserTrialPeriodExpirationChecker implements UserDetailsChecker {
    @Override
    public void check(UserDetails user) {
        if( /* whatever way you check expiration */ ) {
            throw new TrialPeriodExpiredException();
        }

        if (!user.isAccountNonLocked()) {
            throw new LockedException("User account is locked");
        }

        if (!user.isEnabled()) {
            throw new DisabledException("User is disabled");
        }

        if (!user.isAccountNonExpired()) {
            throw new AccountExpiredException("User account has expired");
        }
    }
}

最後の 3 つのチェックは有効期限のチェックとは関係ありませんが、デフォルトの実装 ( AbstractUserDetailsAuthenticationProvider.DefaultPreAuthenticationChecks) がこのクラスによってオーバーライドされるため、ここでチェックする必要があります。デフォルトの実装はプライベートな内部クラスであるため、単純に拡張することはできませんが、そこからコードをコピーしてロック/無効化などを防ぐ必要があります。ユーザーがログインできないようにします。

すべての準備が整ったら、ユーザーがランディングする価格設定ページの URL にExceptionMappingAuthenticationFailureHandlerマップするを構成します。TrialPeriodExpiredException

<form-login authentication-failure-handler-ref="exceptionMapper" ... />

...

<bean id="exceptionMapper" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler" >
    <property name="exceptionMappings">
        <map>
            <entry key="your.package.TrialPeriodExpiredException" value="/pricing"/>
        </map>
    </property>
</bean>
于 2013-03-04T16:46:06.620 に答える