Spring返回401而不是200状态

时间:2018-10-18 09:25:00

标签: java spring-boot jwt

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

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;
    }
}

测试类:

@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);
        }
    }
}

如果有人会对其余的代码感兴趣,请访问以下链接:repository

3 个答案:

答案 0 :(得分:2)

好的。首先第一件事

EmailPassword正确传递

问题在这里

public SignedJWT authenticate(final String email, final String password){
        try {
            System.out.println("test => "+email+" : "+password);
            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) {
            authException.printStackTrace();
            LOGGER.debug("Authentication failed for user:\"" + email + ".\" Reason " + authException.getClass());
        }
        System.out.println("return nulll");
        return null;
    }

如果运行测试用例,它将引发以下错误

org.springframework.security.authentication.BadCredentialsException: Bad credentials
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:98)
    at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:166)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:504)
    at com.github.springjwt.security.jwt.service.AuthenticationServiceUsernamePassword.authenticate(AuthenticationServiceUsernamePassword.java:30)
    at com.github.springjwt.web.api.controller.AuthController.authenticate(AuthController.java:31)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImp

这意味着您的测试用例的usernamepasswordUserRepository类用户详细信息不匹配

在您的UserRepository班上  您需要设置一个正确的哈希密码及其设置为null的盐值。

调用authenticate.authenticate时,它会在内部获取密码和哈希值,并将其与传递的值进行匹配。

如果值不匹配,则会抛出错误的凭据错误

P.S:我在本地运行代码后得出了这个结论

答案 1 :(得分:1)

您的代码大部分是正确的,在您的控制器定义中有误:

public ResponseEntity<String> authenticate(String email, String password, HttpServletRequest request,
                                           HttpServletResponse response){

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

public ResponseEntity<String> authenticate(@RequestBody String email, @RequestBody String password, HttpServletRequest request,
                                           HttpServletResponse response){

但是,如果您的整个控制器将用作API,则您也可以使用@RestController来注释控制器,该命令告诉spring对每个参数使用@RequestBody,并且每个方法都应使用{{1 }},它将告诉spring应该将返回值转换为JSON(对于API来说很方便)。

参考文献:

Spring’s RequestBody and ResponseBody Annotations

答案 2 :(得分:0)

您已经向单元测试用例添加了参数。不是有效载荷。如果添加有效负载,则必须使用@RequestBody。在这里,您必须使用@RequestParam。在控制器中使用以下代码:

public ResponseEntity<String> authenticate(@RequestParam String email, @RequestParam String password, HttpServletRequest request,HttpServletResponse response){
 ..do stuff
}

这可以..!