spring-security 使用Sping Boot 和vanilla java的基于表单的身份验证

goqiplq2  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(183)

我正在尝试实现基于表单的身份验证。身份验证基于用户,基于Roles ADMINUSER。当我运行自定义登录url .loginProcessingUrl("/admin/login")时,身份验证失败,这意味着
1.我得到一个HttpStatus OK
1.任何人都可以登录,即使您没有注册
但是只要我注解掉.loginProcessingUrl("/admin/login")以使用Spring Customs登录页面,它就可以工作了。
我已经看了各种各样的例子,但是没有什么能把我推向正确的方向。我不知道这是不是因为我没有把会话ID保存在User实体类中(注意:我还没有保存会话ID,因为我正在尝试了解基于表单的身份验证的基本原理),或者我的JS有问题。
注:在启动此应用程序时,我将虚拟用户注入一个Role ADMIN和其他两个USERS
这里是我的SecurityFilterChainSecurityConfig Class

@Bean
    public SecurityFilterChain filterChain1(HttpSecurity httpSecurity) throws Exception {

        return httpSecurity
                .cors() //
                .and() //
                .csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests((auth) -> auth
                        .antMatchers("/admin/**", "/secured/**")
                        .hasRole(ADMIN.name())
                )
                .formLogin() //
                .loginProcessingUrl("/admin/login")
                .and()
                // logout TODO
//                .logout()
//                .logoutUrl("/admin/logout")
//                .and()
                .build();
    }

管理员登录控制器API(不是它有一个全局请求Map@RequestMapping(“/admin”))

@PostMapping(path = "/login")
    public ResponseEntity<?> login(@Valid @RequestBody User user) {
        System.out.println("Status " + userDTOService.confirmUser(user));

        if (!userDTOService.confirmUser(user)) {
            return new ResponseEntity<>(!userDTOService.confirmUser(user), BAD_REQUEST);
        }

        return new ResponseEntity<>(userDTOService.confirmUser(user), FOUND);
    }

用于确认用户是否存在的服务类

public Boolean confirmUser(User user) {
        /*
        * Check if username exist in the database
        * then check if the password provided equals password in database
        * Then check if user is an admin
        * */
        System.out.println(user);
        String userName = user.getUserName();
        String password = user.getPassword();
        Optional<User> findUser = userRepository.findUserByUserName(userName);

        return findUser
                .stream()
                .anyMatch(param ->
                        param.getPassword().equals(password)
                        && param.getRole().equals(ADMIN)
                );
    }

vanilla js登录

const signIn = () => {
    formElement.addEventListener("submit", (event) => {
        event.preventDefault();

        const formD = new FormData(event.target);

        fetch(LOGIN, {
            method: "POST",
            body: formD
        }).then(async (response) => {
            if (response.ok) {
                // window.location.href = "../static/new.html";
                console.log("Success");
                return response.json();
            }
            const body = await response.json();
            throw new Error(body.message);
        })
        .catch((error) => {
            console.log(error);
        });

    })
}

另外,由于一些奇怪的原因,我得到了一个来自登录错误console.log(error);的语法错误SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

sg24os4d

sg24os4d1#

我想出了答案。
1.在使用REST API时,使用.formLogin()和.loginProcessingUrl()是错误的。这是因为这些方法用于Springs内置前端ThymeLeaf。
1.使用FormData是错误的,因为它是用于上传文件的,所以我创建了一个对象。有关FormData here的更好解释的文档。
1.因为我使用的是基本身份验证,所以我需要在头中传递用户凭据。
客户端逻辑

const signIn = (LOGIN) => {
    form.addEventListener("submit", (event) => {
        event.preventDefault();

        const formD = {
                        "username": name.value,
                        "password": password.value
                    }
        let authorizationData = 'Basic ' + btoa(name.value + ':' + password.value);

        fetch(LOGIN, {
            method: "POST",
            headers: {
                'Content-Type': 'application/json',
                "Authorization": authorizationData
            },
            body: JSON.stringify(formD)
        }).then(async (response) => {

            if (response.ok) {
                window.localStorage.setItem("Authorization", authorizationData)
                window.location.href = "../static/new.html";
                return response.json();
            }
            const body = await response.json();
            throw new Error(body.message);
        })
        .then ((data) => {
            console.log("Data " + data);
        })
        .catch((err) => {
            console.log("Error " + err.message);
        });

    })
}

安全过滤器

.cors() //
                    .and() //
                    .csrf(csrf -> csrf.ignoringAntMatchers("/h2-console/**").disable())
                    .authorizeHttpRequests((auth) -> auth
                            .antMatchers("/unsecured/**", "/admin/login", "/h2-console/**") //
                            .permitAll() //
                            .anyRequest().authenticated()
                    )
                    .sessionManagement(sessions -> sessions.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                    .headers(headers -> headers.frameOptions().sameOrigin())
                    .httpBasic()
                    .and()
                    .build();

相关问题