Смена пароля с помощью Spring Security
Я использую,
- Spring Framework 4.0.0 RELEASE (GA)
- Spring Security 3.2.0 RELEASE (GA)
- Struts 2.3.16
в котором я использую,
org.springframework.security.authentication.dao.DaoAuthenticationProvider
для аутентификации. мой spring-security.xml
Файл выглядит следующим образом.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http pattern="/Login.jsp*" security="none"></http>
<http auto-config='true' use-expressions="true" disable-url-rewriting="true" authentication-manager-ref="authenticationManager">
<session-management session-fixation-protection="newSession">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
<csrf/>
<headers>
<xss-protection />
<frame-options />
<!--<cache-control />-->
<!--<hsts />-->
<content-type-options /> <!--content sniffing-->
</headers>
<intercept-url pattern="/admin_side/**" access="hasRole('ROLE_ADMIN')" requires-channel="any"/>
<form-login login-page="/admin_login/Login.action" authentication-success-handler-ref="loginSuccessHandler" authentication-failure-handler-ref="authenticationFailureHandler"/>
<logout logout-success-url="/admin_login/Login.action" invalidate-session="true" delete-cookies="JSESSIONID"/>
</http>
<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsService"/>
<beans:property name="passwordEncoder" ref="encoder" />
</beans:bean>
<beans:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref bean="daoAuthenticationProvider" />
</beans:list>
</beans:property>
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService"/>
</authentication-manager>
<beans:bean id="loginSuccessHandler" class="loginsuccesshandler.LoginSuccessHandler"/>
<beans:bean id="authenticationFailureHandler" class="loginsuccesshandler.AuthenticationFailureHandler" />
<global-method-security secured-annotations="enabled" proxy-target-class="false" authentication-manager-ref="authenticationManager">
<protect-pointcut expression="execution(* admin.dao.*.*(..))" access="ROLE_ADMIN"/>
</global-method-security>
</beans:beans>
Реализация UserDetailsService
как следует.
@Service(value="userDetailsService")
public final class UserDetailsImpl implements UserDetailsService {
@Autowired
private final transient UserService userService = null;
@Autowired
private final transient AssemblerService assemblerService = null;
@Override
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
UserTable userTable = userService.findUserByName(userName);
if (userTable == null) {
throw new UsernameNotFoundException("User name not found.");
} else if (!userTable.getEnabled()) {
throw new DisabledException("The user is disabled.");
} else if (!userTable.getVarified()) {
throw new LockedException("The user is locked.");
}
//Password expiration and other things may also be implemented as and when required.
return assemblerService.buildUserFromUserEntity(userTable);
}
}
И следующее - это просто вспомогательный сервис, который преобразует пользовательский объект, который должен использоваться Spring User
объект.
@Service(value="assembler")
@Transactional(readOnly = true, propagation=Propagation.REQUIRED)
public final class AssemblerDAO implements AssemblerService {
@Override
public User buildUserFromUserEntity(UserTable userTable) {
String username = userTable.getEmailId();
String password = userTable.getPassword();
boolean active = userTable.getEnabled();
boolean enabled = active;
boolean accountNonExpired = active;
boolean credentialsNonExpired = active;
boolean accountNonLocked = userTable.getVarified();
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (UserRoles role : userTable.getUserRolesSet()) {
authorities.add(new SimpleGrantedAuthority(role.getAuthority()));
}
return new User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
}
Нет необходимости обращаться к этим классам.
Мой вопрос заключается в том, что при использовании,
org.springframework.security.provisioning.JdbcUserDetailsManager
UserDetailsManager
может быть введен в контроллер и его
public void changePassword(String oldPassword, String newPassword) throws AuthenticationException {
//...
}
Метод может быть использован для изменения пароля. Я никогда не пробовал это, но это может быть примерно реализовано следующим образом.
<bean id="jdbcUserService" class="org.springframework.security.provisioning.JdbcUserDetailsManager">
<property name="dataSource" ref="datasource" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
и в контроллере его следует вводить следующим образом.
@Autowired
@Qualifier("jdbcUserService")
public UserDetailsManager userDetailsManager;
Есть ли какая-либо возможность, предоставляемая Spring security в подходе, который я использую, или достаточно простого простого метода в DAO для изменения пароля текущего вошедшего в систему пользователя? Пожалуйста, предложите, если я делаю что-то не так!
Это содержание может быть слишком большим, чтобы ответить на этот вопрос, но я спрашиваю об этом, потому что это нечто довольно экспериментальное.
2 ответа
Я согласен с ответом @jhadesdev;
Обратите внимание, что, позвонив в Spring JdbcUserDetailsManager.changePassword()
Spring обновляет держатель контекста, а также обновляет базу данных новым паролем.
Spring не обрабатывает cookie, поскольку не заставляет ваше приложение быть веб-приложением. поэтому я думаю, что в этом случае слой более высокого уровня в вашем приложении должен обновить сеанс.
PS - из любопытства - как вы реализовали процесс регистрации, забыли пароль и т. Д.? Весна тоже не справляется. Я написал проект, который заботится об этих потоках...
Метод для изменения пароля является хорошим решением, так как в весенней безопасности для этого нет специальных функций.
Причина, по которой в весенней безопасности не существует никакой специальной функциональности, заключается в том, что она не нужна при использовании сеанса.
Текущий сеанс пользователя, идентифицированный cookie-файлом JSESSIONID, все еще находится в браузере пользователя и будет действительным сеансом после смены пароля.
Когда старый пароль проверялся в последний раз, когда пользователь входил в систему, генерировался файл cookie, который сохранялся в карте действительных файлов cookie в памяти.
Временный токен аутентификации (cookie) все еще действителен и имеет макс. время жизни и изменение пароля в базе данных не повлияет на текущую сессию.