【问题标题】:Authentication failed (Bad Credentuals) in Spring Security with hibernate for REST使用休眠的 REST 在 Spring Security 中身份验证失败(错误凭证)
【发布时间】:2017-07-30 23:38:39
【问题描述】:

我用 spring-data-rest 创建了一个 spring boot 应用程序。

我的 Rest API 运行良好。然后我导入了spring security。参考了一些网络资源,我也做了配置。

但是,每次我发送请求时,我都会收到 Bad Credential Error 以下是我的代码

用户.java

package com.innaun.model;

import org.springframework.data.rest.core.annotation.RestResource;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.HashSet;
import java.util.Set;

@Entity
public class User {

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

    @Column(unique = true, nullable = false)
    private String username;

    @NotNull
    @RestResource(exported = false  )
    private String password;

    @NotNull
    private boolean enabled;

    @OneToMany
    private Set<UserRole> userRoles = new HashSet<UserRole>(0);

    public User() {
    }

    public User(String username, String password, boolean enabled) {
        this.username = username;
        this.password = password;
        this.enabled = enabled;
    }

    public Set<UserRole> getUserRoles() {
        return userRoles;
    }

    public void setUserRoles(Set<UserRole> userRoles) {
        this.userRoles = userRoles;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    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 boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}

UserRole.java

package com.innaun.model;

import javax.persistence.*;
import javax.validation.constraints.NotNull;

@Entity
public class UserRole {

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

    @NotNull
    private String userRole;

    @ManyToOne
    private User user;

    public UserRole() {
    }

    public UserRole(String userRole, User user) {
        this.userRole = userRole;
        this.user = user;
    }

    public Long getUserRoleId() {
        return userRoleId;
    }

    public void setUserRoleId(Long userRoleId) {
        this.userRoleId = userRoleId;
    }

    public String getUserRole() {
        return userRole;
    }

    public void setUserRole(String userRole) {
        this.userRole = userRole;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

UserRepository.java

package com.innaun.model;

import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource
public interface UserRepository extends CrudRepository<User, Long>{
    User findByUsername(@Param("user") String user);
}

UserRoleRepository.java

package com.innaun.model;

import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource
public interface UserRoleRepository extends CrudRepository<UserRole, Long> {
}

AppUserDetailsS​​ervice.java

package com.innaun.model;

import com.innaun.model.UserRepository;
import com.innaun.model.UserRole;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.beans.factory.annotation.Autowired;
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 javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service("appUserDetailsService")
public class AppUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;


    @Transactional
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        com.innaun.model.User user = userRepository.findByUsername(s);

        List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRoles());

        return buildUserForAuthentication(user, authorities);
    }

    private User buildUserForAuthentication(com.innaun.model.User user, List<GrantedAuthority> authorities){
                return new User(user.getUsername(), user.getPassword(), user.isEnabled(), true, true, true, authorities);
    }

    private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles){
        Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

        for (UserRole userRole : userRoles){
            setAuths.add(new SimpleGrantedAuthority(userRole.getUserRole()));
        }

        List<GrantedAuthority> result = new ArrayList<GrantedAuthority>(setAuths);

        return result;
    }


}

ApplicationRESTSecurity.java

package com.innaun;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.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;


@Configuration
@EnableWebSecurity
public class ApplicationRESTSecurity extends WebSecurityConfigurerAdapter {

    @Qualifier("appUserDetailsService")
    @Autowired
    UserDetailsService userDetailsService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().fullyAuthenticated()
                .and().httpBasic()
                .and().csrf()
                .disable();
    }
}

另外,我添加了以下内容以将测试用户添加到数据库

package com.innaun;

import com.innaun.model.User;
import com.innaun.model.UserRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class PitchuApplication {

    public static void main(String[] args) {
        SpringApplication.run(PitchuApplication.class, args);
    }

    @Bean
    CommandLineRunner init(UserRepository userRepository) {

        return (args) -> {
            userRepository.save(new User("myuser", "mypassword", true));
        };
    }

}

和我想的一样,数据库现在有了上面的用户,并且启用了用户。

Screenshot of the User data table

所有其他表格都是空白的。

但是当我尝试卷曲时

curl -u myuser:mypassword localhost:8080

它返回了

{"timestamp":1489090315435,"status":401,"error":"Unauthorized","message":"Bad credentials","path":"/"}

谁能解释我哪里出错了。

【问题讨论】:

  • 除此之外,我还得到了 WARN 2017-03-10 01:50:05.958 WARN 18627 --- [nio-8080-exec-3] osscbcrypt.BCryptPasswordEncoder : Encoded password does看起来不像 BCrypt

标签: spring hibernate rest security authentication


【解决方案1】:

您的配置对我来说看起来不错。所以,我最好的猜测是,您数据库中的 password 列的长度小于 60,这是 BCrypt 将产生的哈希长度。

【讨论】:

  • 谢谢,但我发现了问题所在。原因是我使用了未编码的密码来持久化。我仍然在其他区域使用相同的配置
【解决方案2】:

我想通了。这是一个如此简单的错误。我用来在 userRepository 中保存新用户的密码是原始的而不是加密的。我想通了:

//Create a new password encoder
private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

//Encode the password
String password = "mypassword";
String hashedPassword = passwordEncoder.encode(password);

//Create the user with the encoded password
User user = new User(myuser, hashedPassword, true);

//then persist
userRepository.save(user);

【讨论】:

    猜你喜欢
    • 2014-02-18
    • 2015-07-28
    • 1970-01-01
    • 2012-08-15
    • 2022-08-16
    • 2017-10-03
    • 2013-12-05
    • 2015-06-08
    • 2013-11-13
    相关资源
    最近更新 更多