0

我正在尝试使用散列密码填充数据库,然后通过匹配我通过登录表单提交的数据来登录我的应用程序,就像典型的散列密码应该如何工作一样。我正在使用 spring security 和 spring boot,到目前为止,我知道登录表单正在工作,因为我收到了 error Encoded password does not look like BCrypt。而且我知道当我将用户提交到数据库时它不起作用,因为我只是在数据库的密码列中看到一个纯字符串。我真的不确定我要去哪里错了。

这是我的用户对象

package com.example.objects;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;

import com.example.security.PasswordCrypto;
import com.example.security.RoleEnum;

@Entity
@Table(name = "users")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Version
private Long version;

@Column(name = "username")
private String username;

@Column(name = "password")
private String password;

@Column(name = "email")
private String email;

@Column(name = "termsOfService")
private Boolean termsOfService;

@OneToMany(mappedBy = "user")
private Set<UserRole> roles;

@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<QuestionAnswerSet> questionAnswerSet;


public static User createUser(String username, String email, String password) {
    User user = new User();

    user.username = username;
    user.email = email;
    user.password = PasswordCrypto.getInstance().encrypt(password);

    if(user.roles == null) {
        user.roles = new HashSet<UserRole>();
    }

    //create a new user with basic user privileges
    user.roles.add(
            new UserRole(
                    RoleEnum.USER.toString(),
                    user
            ));

    return user;
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public Long getVersion() {
    return version;
}

public void setVersion(Long version) {
    this.version = version;
}

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public Boolean getTermsOfService() {
    return termsOfService;
}

public void setTermsOfService(Boolean termsOfService) {
    this.termsOfService = termsOfService;
}

public Set<QuestionAnswerSet> getQuestionAnswerSet() {
    return questionAnswerSet;
}

public void setQuestionAnswerSet(Set<QuestionAnswerSet> questionAnswerSet) {
    this.questionAnswerSet = questionAnswerSet;
}

public Set<UserRole> getRoles() {
    return roles;
}

public void setRoles(Set<UserRole> roles) {
    this.roles = roles;
}
}

这是我的安全配置

package com.example.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private static PasswordEncoder encoder;

    @Autowired
    private UserDetailsService customUserDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
        .csrfTokenRepository(csrfTokenRepository());

        http
        .authorizeRequests()
            .antMatchers("/","/home","/register", "/result").permitAll()
            .anyRequest().authenticated();

        http
        .formLogin()
             .loginPage("/login")
                .permitAll()
                .and()
             .logout()
                .permitAll();

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        if(encoder == null) {
            encoder = new BCryptPasswordEncoder();
        }

        return encoder;
    }

    private CsrfTokenRepository csrfTokenRepository() 
    { 
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); 
        repository.setSessionAttributeName("_csrf");
        return repository; 
    }
}

我的用户详情服务

包 com.example.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.example.dao.UserDao;
import com.example.objects.UserRole;

@Service
@Qualifier("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    @Transactional
    @Override
    public UserDetails loadUserByUsername(final String username)
            throws UsernameNotFoundException {

        com.example.objects.User user = userDao.findByUsername(username);
        List<GrantedAuthority> authorities = buildUserAuthority(user.getRoles());

        return buildUserForAuthentication(user, authorities);

    }

    private User buildUserForAuthentication(com.example.objects.User user,
                                            List<GrantedAuthority> authorities) {
        return new User(user.getUsername(), user.getPassword(), authorities);
    }

    private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {

        Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

        // Build user's authorities
        for (UserRole userRole : userRoles) {
            setAuths.add(new SimpleGrantedAuthority(userRole.getRoleName()));
        }

        return new ArrayList<GrantedAuthority>(setAuths);
    }
}

和密码加密

package com.example.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;

public class PasswordCrypto {

    @Autowired
    private PasswordEncoder passwordEncoder;

    private static PasswordCrypto instance;

    public static PasswordCrypto getInstance() {
        if(instance == null) {
            instance = new PasswordCrypto();
        }

        return instance;
    }

    public String encrypt(String str) {
        return passwordEncoder.encode(str);
    }
}

如果有人知道我做错了什么并且可以帮助我,那就太好了,如果我需要显示更多代码,请告诉我。提前致谢。

4

2 回答 2

0

像这样使用编码器到用户存储库:

public class UserRepositoryService implements UserService {
    private PasswordEncoder passwordEncoder;

    private UserRepository repository;

    @Autowired
    public UserRepositoryService(PasswordEncoder passwordEncoder,
            UserRepository repository) {
        this.passwordEncoder = passwordEncoder;
        this.repository = repository;
    }

    private boolean emailExist(String email) {
        User user = repository.findByEmail(email);
        if (user != null) {
            return true;
        }
        return false;
    }

    private String encodePassword(RegistrationForm dto) {
        String encodedPassword = null;
        if (dto.isNormalRegistration()) {
            encodedPassword = passwordEncoder.encode(dto.getPassword());
        }

        return encodedPassword;
    }

    @Transactional
    @Override
    public User registerNewUserAccount(RegistrationForm userAccountData)
            throws DuplicateEmailException {
        if (emailExist(userAccountData.getEmail())) {
            LOGGER.debug("Email: {} exists. Throwing exception.",
                    userAccountData.getEmail());
            throw new DuplicateEmailException("The email address: "
                    + userAccountData.getEmail() + " is already in use.");
        }
        String encodedPassword = encodePassword(userAccountData);

        User.Builder user = User.getBuilder().email(userAccountData.getEmail())
                .firstName(userAccountData.getFirstName())
                .lastName(userAccountData.getLastName())
                .password(encodedPassword)
                .background(userAccountData.getBackground())
                .purpose(userAccountData.getPurpose());

        if (userAccountData.isSocialSignIn()) {
            user.signInProvider(userAccountData.getSignInProvider());
        }
        User registered = user.build();
        return repository.save(registered);
    }
}

有关更多信息,请查看此 repo

https://bitbucket.org/sulab/biobranch/src/992791aa706d0016de8634ebb6347a81fe952c24/src/main/java/org/scripps/branch/entity/User.java?at=default&fileviewer=file-view-default

于 2015-10-31T04:05:48.080 回答
0

我的问题是我需要user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));在保存用户之前添加我的 UserController Post 方法

于 2015-11-03T02:16:33.933 回答