应用程序当前使用 Spring Security,其简单的用户名和密码由 Spring 自动生成的登录表单处理。用户名是有效的电子邮件地址。
我还有其他代码,可以向用户发送一封电子邮件,其中 URL 中包含 session ID,以验证电子邮件地址。它还会向用户发送一 strip 有自定义 PIN 码的短信,以验证他们的电话号码。注册站点、验证电子邮件和验证电话号码的步骤需要多种 Controller 方法和步骤。
是否有一种快速简便的方法可以将代码添加到现有的 Controller 方法中,只需声明用户已登录? 这将使用现有的 spring 安全配置,并通过声明用户来简单地进行扩展已登录。
例如,在 Controller 方法中:
//confirmed email
//confirmed phone number
//confirmed password
loggedin = true;
<小时/>
澄清:
<小时/>每次用户登录时都需要发送并验证确认文本 pin 码和确认电子邮件。如果无法使用简单的编程语句让某人登录,我至少可以吗通过简单的编程语句更改用户的角色?因此,他们使用用户名和密码登录到受限的有条件状态,并被分配“StepOneRole”。然后,他们验证发送给他们的 pin 码,并获得“StepTwoRole”。然后,他们验证发送给他们的电子邮件链接,并且他们的角色更改为“FullUser”,他们可以在其中实际使用网站的安全部分。
我试图避免增加不必要的复杂性,但用户需要每次验证n个因素。
另外,请注意我的 SecurityConfig.java
如下,并使用 UserDetailService
,这在下面的答案之一中提到:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/user-home")
.usernameParameter("j_username")
.passwordParameter("j_password")
.loginProcessingUrl("/j_spring_security_check")
.failureUrl("/login")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login")
.and()
.authorizeRequests()
.antMatchers("/user-home").hasAuthority("USER")
.antMatchers("/j_spring_security_check").permitAll()
.and()
.userDetailsService(userDetailsService);
}
}
最佳答案
以下代码将以编程方式登录用户:
Authentication authentication =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
请注意,上面的 user
是用户对象,实现了 UserDetails
。
同样,要注销用户,可以使用以下代码:
SecurityContextHolder.getContext().setAuthentication(null);
回复您的评论:
我不确定 Spring security 如何在没有用户类或实现 UserDetails
的映射类的情况下使用您的用户和角色。在我的一个项目中,我有一个像这样的映射类:
public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = 5197941260523577515L;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public UserDetailsImpl(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> authorities = new HashSet<GrantedAuthority>(
user.getRoles().size() + 1);
for (Role role : user.getRoles())
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.name()));
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return authorities;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getEmail();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
因此,我从我的用户对象创建它的一个实例,并使用它以编程方式登录,如下所示:
UserDetailsImpl userDetails = new UserDetailsImpl(user);
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
对第三条评论的回复:
是的,User
是一个自编码类。 Here是包含整个项目源代码的 zip 链接。这是 a video tutorial 的按章节来源的列表,但您只需查看列表中的最后一个。
关于java - 我可以通过自定义方法对用户进行身份验证吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31977103/