简体   繁体   English

请求以 401 未经授权返回

[英]Requests coming back as 401 unauthorized

I recently asked a question very similar to this one but instead of 401 the error I was getting was 403 (Forbbiden), but I changed the entire code so I decided to post a new one specific to this code and this problem.我最近问了一个与这个问题非常相似的问题,但我得到的错误不是 401,而是 403 (Forbbiden),但我更改了整个代码,所以我决定发布一个特定于此代码和此问题的新代码。

I'm trying to create an user logic to my project (for the first time ever) but it has been impossible to implement any kind of security measure.我正在尝试为我的项目创建一个用户逻辑(有史以来第一次),但不可能实施任何类型的安全措施。 I've been stuck in this for days so if anyone knows where I'm wrong I'd be grateful!我已经被困在这几天了,所以如果有人知道我哪里错了,我将不胜感激!

this is my code:这是我的代码:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/users/create", "/users/create/**").permitAll()
                .and()
            .httpBasic();
    }
}
@Data
@Component
public class CreateUserRoleDTO {
    private Integer idUser;
    
    private List<Integer> idsRoles;

    public CreateUserRoleDTO() {
        super();
    }
    
    public CreateUserRoleDTO(Integer idUser, List<Integer> idsRoles) {
        super();
        this.idUser = idUser;
        this.idsRoles = idsRoles;
    }

    public Integer getIdUser() {
        return idUser;
    }

    public void setIdUser(Integer idUser) {
        this.idUser = idUser;
    }

    public List<Integer> getIdsRoles() {
        return idsRoles;
    }

    public void setIdsRoles(List<Integer> idsRoles) {
        this.idsRoles = idsRoles;
    }       
}
@Service
public class CreateRoleUserService {
    
    @Autowired
    private UserRepository repo;

    @Autowired
    private CreateUserRoleDTO createUserRoleDTO;
    
    public Users execute(CreateUserRoleDTO createUserRoleDTO) {
        Optional<Users> userExists=repo.findById(createUserRoleDTO.getIdUser());
        List<Roles> roles=new ArrayList<>();
        
        if (userExists.isEmpty()) {
            throw new Error("User does not exist");
        }
        roles=createUserRoleDTO.getIdsRoles().stream().map(role -> {
            return new Roles(role);
        }).collect(Collectors.toList());
        
        Users user=userExists.get();
        user.setRole(roles);
        
        repo.save(user);
        return user;    
    }
    @Entity
    @Table(name="users_table")
    public class Users implements Serializable{
        
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        private Integer id;
        
        @Column(unique=true)
        private String login;
        
        @Column(unique=true)
        private String email; 
        
        private String password;
        
        @ManyToMany
        private List<Roles> role; 
        
    }

(plus the getters and setters and constructors) (加上 getter 和 setter 以及构造函数)

data.sql : data.sql

INSERT INTO `ROLES`(`ID`, `NAME`) VALUES(1, 'USER');
INSERT INTO `ROLES`(`ID`,`NAME`) VALUES(2, 'ADMIN');

-> the code runs fine, it even gives me the security password, the problem appears when I try to make any kind of requests. -> 代码运行正常,它甚至给了我安全密码,当我尝试发出任何类型的请求时出现问题。

The entire code if I've left anything out: https://github.com/vitoriaacarvalho/backend-challenge-very-useful-tools-to-remember-如果我遗漏了任何内容,则完整代码: https://github.com/vitoriaacarvalho/backend-challenge-very-useful-tools-to-remember-

An authentication configuration is missing in your SecurityConfig .您的SecurityConfig中缺少身份验证配置。 For example, try adding the following to your configure method:例如,尝试将以下内容添加到您的configure方法中:

http.httpBasic();

Additionally, your security configuration is missing a default authorization rule, so authentication is not actually required.此外,您的安全配置缺少默认授权规则,因此实际上不需要身份验证。 You can try adding .anyRequest().authenticated() to test this out.您可以尝试添加.anyRequest().authenticated()来测试这一点。

Here's a configuration which uses the lambda syntax available in the DSL and is ready to be upgraded to Spring Security 6:这是一个使用 DSL 中可用的 lambda 语法的配置,并准备升级到 Spring Security 6:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authorize) -> authorize
                .antMatchers("/users/create", "/users/create/**").permitAll()
                .anyRequest().authenticated()
            )
            .httpBasic(Customizer.withDefaults());

        // Disable CSRF for testing.
        // TODO: Delete the following line and learn about CSRF!
        http.csrf().disable();

        return http.build();
    }

    @Bean // Automatically injected into Spring Security
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // Note: We don't configure a UserDetailsService since it is already 
    // annotated @Service and therefore already published as an @Bean.

}

Unfortunately, I also spotted a few other mistakes in your application that made it not work.不幸的是,我还在您的应用程序中发现了其他一些导致它无法运行的错误。

It looks like you have a mistake in the JPQL used to query the user for the UserDetailsService .看起来您在用于向用户查询UserDetailsService的 JPQL 中有错误。 The WHERE clause should be where u.login =:username (add a u. ). WHERE 子句应该是where u.login =:username (添加一个u. )。

You also have the if-statement inverted as well.您还反转了 if 语句。 When throwing a UsernameNotFoundException (a better exception than Error for this case), it would look like:当抛出UsernameNotFoundException (在这种情况下比Error更好的异常)时,它看起来像:

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Users user = repo.findByUsernameFetchRoles(username);
        if (user == null) {
            throw new UsernameNotFoundException("User does not exist!");
        }

        return UserPrincipal.create(user);
    }

Lastly, the constructor of your Users class was not assigning user data from the user parameter.最后,您的Users class 的构造函数未从user参数分配用户数据。 It should be:它应该是:

    public UserPrincipal(Users user) {
        this.login = user.getLogin();
        this.password = user.getPassword();
        ...
    }

With those changes, authentication works and you're on your way to learning Spring Security!有了这些更改,身份验证就可以工作了,您就可以开始学习 Spring 安全性了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM