Spring返回401而不是200状态

mar*_*usz 5 java jwt spring-boot

我写了一个应用程序作为学习Spring的一部分,但是当我测试身份验证时,我收到401状态而不是200.我正在寻找错误的原因,在我看来该行Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(email, password));返回null.但是,我不知道如何解决这个问题.

@Component
public class AuthenticationServiceUsernamePassword {
    private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationServiceUsernamePassword.class);
    @Autowired
    @Qualifier("customAuthenticationManager")
    private AuthenticationManager authenticationManager;
    @Autowired
    private TokenManager tokenManager;

    public SignedJWT authenticate(final String email, final String password){
        try {
            Authentication authentication = authenticationManager
                .authenticate(new UsernamePasswordAuthenticationToken(email, password));        
            SecurityContextHolder.getContext()
                .setAuthentication(authentication);

            if (authentication.getPrincipal() != null) {
                return tokenManager.createNewToken((PrincipalUser) authentication.getPrincipal());
            }
        } catch (AuthenticationException authException) {
            LOGGER.debug("Authentication failed for user:\"" + email + ".\" Reason " + authException.getClass());
        }

        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

调节器

@Controller
public class AuthController {
    @Value("${jwt.result}")
    private String defaultTokenResponse;
    @Autowired
    private AuthenticationServiceUsernamePassword authUserPassword;

    @RequestMapping(value = "/authentication", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<String> authenticate(String email, String password, HttpServletRequest request,
                                           HttpServletResponse response){
        if (email != null && password != null){
            try {
                SignedJWT token = authUserPassword.authenticate(email, password);

                if (token != null){
                    return new ResponseEntity<String>(String.format(defaultTokenResponse, token.serialize()),
                        HttpStatus.OK);
                } else {
                    return new ResponseEntity<String>(HttpStatus.UNAUTHORIZED);
                }
            } catch (BadCredentialsException badCredentials) {
                return new ResponseEntity<String>(HttpStatus.UNAUTHORIZED);
            }
        } else {
            return new ResponseEntity<String>(HttpStatus.UNAUTHORIZED);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
public class ConnectControllerTest {
    protected MockMvc mockMvc;
    @Autowired
    private WebApplicationContext context;
    @Autowired
    private Filter springSecurityFilterChain;

    @Before
    public void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context)
            .addFilters(springSecurityFilterChain)
            .defaultRequest(get("/"))
            .build();
    }

    @Test
    public void shouldTestAuthentication() throws Exception {
        String result = mockMvc.perform(post("/authentication")
            .param("email", "user@test.pl").param("password", "password"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.token").exists())
            .andReturn().getResponse().getContentAsString();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果有人对其余的代码感兴趣,那么链接:repository

Sve*_*ort 2

您的代码大部分是正确的,但在您的控制器定义中出现了错误:

\n\n
public ResponseEntity<String> authenticate(String email, String password, HttpServletRequest request,\n                                           HttpServletResponse response){\n
Run Code Online (Sandbox Code Playgroud)\n\n

默认情况下,Spring 不知道如何检索电子邮件和密码变量。您需要使用@RequestBody注释来注释它们,例如:

\n\n
public ResponseEntity<String> authenticate(@RequestBody String email, @RequestBody String password, HttpServletRequest request,\n                                           HttpServletResponse response){\n
Run Code Online (Sandbox Code Playgroud)\n\n

然而,如果你的整个控制器将作为一个API,你也可以注释你的控制器,@RestController告诉spring使用@RequestBody每个参数,并且每个方法都应该注释@ResponseBody,这将告诉spring返回值应该转换为JSON(这是方便 API)。

\n\n

参考:

\n\n

Spring\xe2\x80\x99s RequestBody 和 ResponseBody 注解

\n