Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用bcrypt的Spring身份验证_Java_Spring_Spring Security - Fatal编程技术网

Java 使用bcrypt的Spring身份验证

Java 使用bcrypt的Spring身份验证,java,spring,spring-security,Java,Spring,Spring Security,我正在尝试将bcrypt添加到我的spring应用程序中。无需验证即可正常工作。但当我尝试使用bcrypt进行编码时,我在尝试登录时会得到“原因:错误的凭据” 我的用户模型如下所示 @Entity @Table(name="users") // user is a reserved word in postgresql public class User extends BaseEntity { private PasswordEncoder passwordEncoder = new

我正在尝试将bcrypt添加到我的spring应用程序中。无需验证即可正常工作。但当我尝试使用bcrypt进行编码时,我在尝试登录时会得到“原因:错误的凭据”

我的用户模型如下所示

@Entity
@Table(name="users") // user is a reserved word in postgresql
public class User extends BaseEntity {
    private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    ...
    @Column(nullable=false)
    private String password;

    ...

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        String hashedPassword = passwordEncoder.encode(password);
        this.password = hashedPassword;
    }

    ...
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomUserDetailsService userDetailsService;

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

    private BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
...
}
我的SecurityConfig如下所示

@Entity
@Table(name="users") // user is a reserved word in postgresql
public class User extends BaseEntity {
    private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    ...
    @Column(nullable=false)
    private String password;

    ...

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        String hashedPassword = passwordEncoder.encode(password);
        this.password = hashedPassword;
    }

    ...
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomUserDetailsService userDetailsService;

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

    private BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
...
}

上述情况是否正确?我需要做比我已经做的更多的事情吗?

以下是我将如何设置它

用户表有4个属性(除其他属性外)

  • id(自动递增)
  • 用户名(或电子邮件地址)字段
  • 密码字段
  • 已启用(值将为1或0)
  • 角色表(3个属性)

  • id(自动递增)
  • 用户id(用户表外键)
  • 权威 为这两个表创建Java实体

    Spring安全配置类如下所示:

    @Autowired 
    public void  configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
    String usrsByUnameQry = "SELECT u.email_address, u.password, u.enabled FROM user u WHERE u.email_address=?"; 
    3String authByUnameQry = "SELECT u.email_address, r.authority FROM user u, role r WHERE u.id=r.user_id AND u.email_address=?"; 
    
    auth 
    .eraseCredentials(false) 
    .jdbcAuthentication() 
    .dataSource(dataSource) 
    .passwordEncoder(passwordEncoder()) 
    .usersByUsernameQuery(usrsByUnameQry) 
    .authoritiesByUsernameQuery(authByUnameQry); 
        } 
    
     @Override 
      protected void configure(HttpSecurity http) throws Exception { 
          http 
             .formLogin() 
                .usernameParameter("username") //username property defined in html form
                .passwordParameter("password") //password property defined in html form
                  // url that holds login form 
                  .loginPage("/signin") 
                  .loginProcessingUrl("/signin/authenticate") 
                  .failureUrl("/loginfail") 
                  // Grant access to users to the login page
                  .permitAll() 
                  .and() 
              .logout() 
                .logoutUrl("/signout") 
                .deleteCookies("JSESSIONID") 
                .logoutSuccessUrl("/signin") 
                .and() 
                       .authorizeRequests() 
                    .antMatchers("/foo/**").permitAll()//Grant access to all (no auth reuired) 
                    .antMatchers("/").hasAnyAuthority("ROLE_USER","ROLE_ADMIN") //Grant access to only users with role "ROLE_USER" or "ROLE_ADMIN"  
      } 
    
     @Bean(name = "authenticationManager") 
     @Override 
     public AuthenticationManager authenticationManagerBean() throws Exception { 
        return super.authenticationManagerBean(); 
       } 
    
     @Bean   
     public BCryptPasswordEncoder passwordEncoder(){ 
            return new BCryptPasswordEncoder(); 
        } 
    
    @Bean 
    public TextEncryptor textEncryptor(){ 
        return Encryptors.noOpText(); 
    } 
    

    我的错误在于没有发布足够的代码。当然,我的用户模型并没有说明全部情况。我还有一个名为SecurityUser的类,我在下面发布了这个类。由于复制构造函数的存在,密码会被散列两次

    public class SecurityUser extends User implements UserDetails {
    
        private static final long serialVersionUID = 867280338717707274L;
    
        public SecurityUser(User user) {
            if(user != null)
            {
                this.setId(user.getId());
                this.setName(user.getName());
                this.setEmail(user.getEmail());
                this.setPassword(user.getPassword());
                this.setRoles(user.getRoles());
            }
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            Set<Role> userRoles = this.getRoles();
    
            if(userRoles != null)
            {
                for (Role role : userRoles) {
                    SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getName());
                    authorities.add(authority);
                }
            }
            return authorities;
        }
    
    ...
    }
    

    愚蠢的问题,但您是否检查了数据库中的密码是否经过哈希处理?是的,到目前为止,它看起来是这样的:$2a$10$6k776rYtY.fn8tdfw08ryogfsqdekqqqpocjcovjf/oT/8FQcQ/oyalry已经尝试过了。没有区别。您可以粘贴密码字段的输出吗?$2a$10$jyaYvkHqgBhesyR8WwfQfe07eV/BVTXobwtI6dtxglGQZ0Zq4CYDi-这是以“密码”作为密码的。好的,但是使用此配置,您将对密码编码两次!一次在实体中,一次在用户服务中。如果您的orm使用setter注入属性,您将在另一次对密码进行编码。删除实体的passwordEncoder属性。这毫无意义。如果在不同的服务项目中分离实体(和DAO),则实体中不应包含类
    PasswordEncoder
    。当然,我将其从模型中删除,仅在服务中包含。谢谢你的输入。好的,用你最新的代码更新你的第一篇文章。添加包含最新更新的编辑节。顺便说一下,我强烈建议您将
    SecurityUser
    User
    分开
    SecurityUser
    不应该扩展
    User
    ,而应该实现
    UserDetails
    。否则,您将能够在
    SecurityUser
    上调用
    UserService.create
    方法,或者从另一个方法创建
    SecurityUser
    。这两种情况应该发生,而且,依我看,这种关系是不正确的。删除代码中的这种继承,也许你会发现代码中有什么错误。上面的代码正在运行。我只是在等待,让我接受我自己的答案。因为安全用户不应该包含任何密码。即使它是在欺骗一个用户,它也不是专用于同样的事情。但是,就像我说的,这只是我的错。如果你希望投票给自己的答案,你可以等很长时间!!谢谢你的意见。我选择了一条有点不同的道路。通过实现自定义UserDetailsService类,您可以摆脱安全配置中的sql。