java - 我可以通过自定义方法对用户进行身份验证吗?

标签 java spring spring-mvc spring-security

应用程序当前使用 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/

相关文章:

spring - 使用 ResponseEntity 进行流式传输并确保 InputStream 关​​闭的正确方法

java - 格式化输出以供 hibernate 实体内查看是否可以接受?

java - 以编程方式创建源文件夹

java - 在 IBM MQ in java 程序中创建主题

java - Spring - ConversionService 没有 @Autowired 因为 ConfigurationPropertiesBindingPostProcessor

java - Spring Batch - 了解 block 大小和 ItemReadListener 之间的行为

java - POST 请求显示 "405 GET not supported"并启用了 Spring 安全性

spring-mvc - ivy - spring-web 有 Unresolved 依赖关系

java - 是否有一个插入订单保留 Set 也实现了 List?

java - 带有 ListActivity 的 Material 设计工具栏