简体   繁体   中英

FastApi 422 Unprocessable Entity, on authentication, how to fix?

Cannot understand even if i delete all inside function and just print something still got this error, but when i use fastapi docs, and try signing with that, it work.

@auth_router.post('/signin')
async def sign_in(username: str = Form(...), password: str = Form(...)) -> dict:
    user = await authenticate_user(username, password)

    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, 
            detail='Invalid username or password',
        )

    user_obj = await User_Pydantic.from_tortoise_orm(user)
    user_token = await generate_token(user_obj)

    return {
        'access_token': user_token,
        'token_type': 'bearer',
    }

Before i use OAuth2PasswordRequestForm, when got 422 error, try another way.

my model is tortoise orm, and when need i convert it to pydantic model, in docs all is work.

JS

handleEvent(signinform, 'submit', e => {
    e.preventDefault();
    if(!isEmpty(signinform)){

        signInUsername = getElement('input[name="username"]', signinform).value;
        signInPassword = getElement('input[name="password"]', signinform).value;
        recaptchaV3 = getElement('[name="g-recaptcha-response"]').value;

        if(recaptchaV3){
            signInData = new FormData();
            signInData.append('username', signInUsername);
            signInData.append('password', signInPassword);

            isLogened = request('POST', '/signin', signInData);
            if(isLogened){
                log(isLogened);
            }
            
        } else{
            alert('Reload Page');
        }

    }

})

authenticate_user func

async def authenticate_user(username: str, password: str):
    user = await User.get(username=username)

    if not user or not user.verify_password(password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, 
            detail='Invalid username or password',
        )
    return user

My request function

const request = (method, url, data = null) => {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest()
        xhr.open(method, url, true)
        xhr.setRequestHeader('Content-Type', 'application/json')
        xhr.onerror = function () {
            console.log(xhr.response);
        };
        xhr.onload = () => {
        if (xhr.status === 200) {
            return resolve(JSON.parse(xhr.responseText || '{}'))
            } else {
                return reject(new Error(`Request failed with status ${xhr.status}`))
            }
        } 
        if (data) {
            xhr.send(JSON.stringify(data))
        } else {
            xhr.send()
        }


    })
}

Although you did not publish the error, who's purpose is to tell you the problem, I'm fairly sure the problem lies in the way you perform the request.

The line

xhr.setRequestHeader('Content-Type', 'application/json')

means that you are sending json data, which is not accepted by the authentication form of openapi. Also, you are stringifying the data into json which, again, is not an accepted format.

Thus, changing the content type to www-form-urlencoded and adding a FormData object to your request's body, will make it work.

You can see it in the github discussions below

https://github.com/tiangolo/fastapi/issues/2740 https://github.com/tiangolo/fastapi/issues/1431

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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