gpt4 book ai didi

spring - 使用 Spring MVC 检查用户订阅试用期是否过期

转载 作者:行者123 更新时间:2023-12-04 05:08:26 25 4
gpt4 key购买 nike

我正在使用 spring MVC 并想检查用户的试用期是否已过期。

我正在使用以下方法使用 Spring Security 获取用户详细信息

  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);
}

现在我的问题是我不想在每个 Controller 中重复编写上面的代码。那么是否有任何常见的地方可以让我检查用户试用期是否到期并将他重定向到定价页面。

我有 CustomUserDetail 类,我在其中从数据库访问用户详细信息并将其放入 spring 安全 session 中。所以我认为这应该是检查用户试用期是否到期的最佳地点,但我不知道如何将用户从此类重定向到定价页面。

我的 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"

最佳答案

您可以设置自定义 UserDetailsCheckerDaoAuthenticationProvider在验证用户之前验证到期日期。
<authentication-provider>配置中的元素会生成 DaoAuthenticationProvider ,但该元素上没有允许您设置其 preAuthenticationChecks 的属性属性(property)。为了解决命名空间配置的这个限制,您必须回退到将该提供程序定义为普通 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>

并通过 <authentication-manager> 中的 id 引用它配置:
<security:authentication-manager>
<security:authentication-provider ref="authenticationProvider"/>
</security:authentication-manager>

以上引用 expirationChecker bean 必须实现 UserDetailsChecker这是一个接收 UserDetails的回调接口(interface)对象,如果用户的试用期已过,您可以在其中抛出特定异常:
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");
}
}
}

请注意,最后三个检查与过期检查无关,但您必须在此处拥有它们,因为默认实现(即 AbstractUserDetailsAuthenticationProvider.DefaultPreAuthenticationChecks)现在已被此类覆盖。由于默认实现是私有(private)内部类,您不能简单地扩展它,而是需要从那里复制代码以防止锁定/禁用/等。用户从登录。

一切就绪后,配置 ExceptionMappingAuthenticationFailureHandler映射您的 TrialPeriodExpiredException到用户应该登陆的定价页面的 URL。
<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>

关于spring - 使用 Spring MVC 检查用户订阅试用期是否过期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15206370/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com