例如,下面的代码试图处理一个简单的登录,使用密码编码器对db表进行身份验证。表单post包括一个“客户端”,一个持久化的IP地址和一些url路径信息,以便在登录后进行深度链接。(对于今天的单页web应用程序来说,这些都是非常基本的东西)我最初使用xml config工作,但是javaConfig让我陷入了困境。
我不知道userDetailsService,AuthenticationManagerBuilder和PasswordEncoder在SecurityConfiguration中是如何交互的。我获取服务的登录数据,但不确定spring authenticationProvider在何处或何时应用,或者我是否需要一个。
我的用户实现UserDetails并保存必需的字段。我在CustomUserDetailsService中填充这些和授予的权限。如果我在服务中使用登录/密码检查db,我如何/何时/为什么需要auth.authenticationProvider(authenticationProvider())?
我的UserDetailsService现在似乎html" target="_blank">执行了两次。
为什么我的大脑那么小,我无法理解这些?:)
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private ClientDAO clientDAO;
@Autowired
private UserDAO userDAO;
public UserDetails loadUserByUsername(String multipartLogon) throws UsernameNotFoundException, DataAccessException {
Boolean canAccess = false;
Long clientId = null;
String userLogon = null;
String password = null;
String id = null;
String entryUrl = null;
String ipAddress = null;
String urlParam = null;
String[] strParts = multipartLogon.split(":");
try {
userLogon = strParts[0];
password = strParts[1];
id = strParts[2];
entryUrl = strParts[3];
ipAddress = strParts[4];
urlParam = strParts[5];
} catch(IndexOutOfBoundsException ioob) { }
Client client = new Client();
if (!"".equals(id)) {
clientId = IdUtil.toLong(id);
client = clientDAO.getClient(clientId);
}
//BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//String encodedPassword = passwordEncoder.encode(password);
//String encodedPassword = "$2a$22$6UiVlDEOv6IQWjKkLm.04uN1yZEtkepVqYQ00JxaqPCtjzwIkXDjy";
User user = userDAO.getUserByUserLogonPassword(userLogon, password); //encodedPassword?
user.isCredentialsNonExpired = false;
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
for (UserRole userRole : userDAO.getUserRolesForUser(user)) {
if (userRole.getRole().getActiveStatus()) {
authorities.add(new SimpleGrantedAuthority(userRole.getRole().getRoleName()));
user.isCredentialsNonExpired = true;
}
}
user.setAuthorities(authorities);
user.setPassword(password); //encodedPassword?
user.setUsername(user.getUserLogon());
user.isAccountNonExpired = false;
user.isAccountNonLocked = false;
List<ClientUser> clientUsers = clientDAO.getClientUsersForUser(user);
for (ClientUser clientUser : clientUsers) {
if (clientUser.getClient().getClientId().equals(client.getClientId())) {
canAccess = true;
break;
}
}
user.isEnabled = false;
if (user.getActiveStatus() && canAccess) {
user.isAccountNonExpired = true;
user.isAccountNonLocked = true;
user.isEnabled = true;
Session session = userDAO.getSessionForUser(user);
if (session == null) { session = new Session(); }
session.setUser(user);
session.setDateLogon(Calendar.getInstance().getTime());
session.setClient(client);
session.setEntryUrl(entryUrl);
session.setUrlParam(urlParam);
session.setIPAddress(ipAddress);
session.setActive(true);
userDAO.persistOrMergeSession(session);
}
return user;
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
CustomUserDetailsService customUserDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService);
auth.authenticationProvider(authenticationProvider());
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(customUserDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/conv/a/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_COURT_ADMIN')")
.antMatchers("/conv/u/**").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN') or hasRole('ROLE_COURT_ADMIN')")
.antMatchers("/**").permitAll()
.and()
.formLogin()
.loginPage("/conv/common/logon")
.usernameParameter("multipartLogon")
.loginProcessingUrl("/conv/common/logon")
.defaultSuccessUrl("/conv/")
.failureUrl("/conv/common/logon?error=1")
.and()
.logout()
.logoutUrl("/conv/common/logout")
.logoutSuccessUrl("/conv/")
.permitAll()
.and()
.rememberMe()
.key("conv_key")
.rememberMeServices(rememberMeServices())
.useSecureCookie(true);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/common/**")
.antMatchers("/favicon.ico");
}
@Bean
public RememberMeServices rememberMeServices() {
TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("conv_key", customUserDetailsService);
rememberMeServices.setCookieName("remember_me_cookie");
rememberMeServices.setParameter("remember_me_checkbox");
rememberMeServices.setTokenValiditySeconds(2678400); //1month
return rememberMeServices;
}
}
我的用户实现UserDetails并保存必需的字段。我在CustomUserDetailsService中填充这些和授予的权限。如果我在服务中使用登录/密码检查db,我如何/何时/为什么需要auth.authenticationProvider(authenticationProvider())?
我想你想要的是:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
}
userDetailsService方法是创建DAOAuthenticationProvider
bean的快捷方式!您不应该同时需要这两种,它只是两种不同的方式来配置相同的东西。authenticationProvider方法用于更多自定义设置。
spring如何接受提交的密码,对其进行编码,并与存储在DB中的密码进行比较?它如何知道使用与创建P/W时使用的盐相同的盐/在创建用户时持久化的盐?
如果您使用的是BCrypt,salt将存储在编码的密码值中。salt是第三个$(美元)符号后的前22个字符。matches方法负责检查密码。
为什么configureGlobal()同时定义Auth.UserDetailsService和Auth.authenticationProvider()同时设置UserDetailsService?
见上文。这可能是用户详细信息加载两次的原因。
更新:奇怪的是,你将密码和其他细节放入你的UserDetailsService。这应该只根据用户名加载user,如下所示:
User user = userDAO.getUserByUserLogonPassword(userLogon);
返回的用户对象应该包含编码的(存储的)密码,而不是输入的密码。Spring Security为您执行密码检查。不应修改UserDetailsService中的User对象。
function getCarData() { return [ {id: 1, name: {first: "Chris", last: "Right"}, password: "plainTextPassword"}, {id: 2, name: {first: "John", last: "Honest"}, password: "txt"}, {id: 3, name: {fi
以下示例描述了如何使用Spring Web MVC框架在表单中使用Password。 首先,让我们使用一个可用的Eclipse IDE,并遵循以下步骤使用Spring Web Framework开发基于动态表单的Web应用程序。 步 描述 1 在Spring MVC - Hello World章节中解释,在com.wenjiangs包下创建一个名为HelloWeb的项目。 2 在com.wenji
主要内容:1.入门,2.设置用户名和密码1.入门 1.启动一个SpringBoot项目 2.导入SpringSecurity相关依赖 3.编写Controller TestController.java 用户是user 密码是刚刚的 2.设置用户名和密码 1.在配置文件中设置 2.在配置类中设置 3.自定义实现类 2.1 配置文件中设置 2.2 在配置类中设置 设置用户名为zZZ,密码为root 2.3 自定义实现类 配置类: 业务类:
试图了解使用Spring Security实现OpenID身份验证的正确方法。 我正在考虑用户尚未在我的应用程序中注册的情况。要注册用户,我需要知道它的OpenID和电子邮件。 当OpenID提供者将用户重定向回我的应用程序时,将调用,但在这种情况下,我只知道用户的OpenID。因此,我抛出,然后,因此无法注册用户。 这里常见的解决办法是什么?如果从返回类似,然后在调用时注册用户,然后返回真正的呢
我是Spring Security的新手,我试图实现自定义的身份验证。令我困扰的是,这个接口只包含一个方法,它只将用户名作为参数并返回。 我想知道为什么这个方法不接受任何密码作为参数。 Spring是如何只根据用户名对用户进行身份验证的?
WinSCP can protect stored passwords by strong AES cipher. In order to protect such sensitive information you need to set a master password. When a master password is not set, stored passwords can be e