java - Spring Security 4 - REST 身份验证失败和 Controller 异常处理程序

标签 java rest spring-mvc spring-security

我正在通过一些示例应用程序学习 Spring Security。我遇到了一些问题。

我正在使用 Spring 4.2.2.RELEASE 和 Spring Security 4.0.2.RELEASE。 这是我的 Spring 安全上下文。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">

    <context:component-scan base-package="com.mvc.sslspring.security" />

    <security:authentication-manager id="authenticationManager">
        <security:authentication-provider>
            <security:user-service>
                <security:user name="aa" password="aa" authorities="ROLE_USER" />
                <security:user name="bb" password="bb"
                    authorities="ROLE_USER, ROLE_ADMIN" />
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>

    <security:http realm="Protected API" use-expressions="true"
        auto-config="false" create-session="stateless" entry-point-ref="restAuthenticationEntryPoint"
        authentication-manager-ref="authenticationManager">

        <security:custom-filter ref="restAuthenticationTokenProcessingFilter"
            position="FORM_LOGIN_FILTER" />
        <security:intercept-url pattern="/authenticate" 
            access="permitAll" />

        <security:intercept-url pattern="/persons"
            access="isAuthenticated() and hasRole('ROLE_ADMIN')" />
        <security:intercept-url pattern="/persons/*"
            access="isAuthenticated() and hasRole('ROLE_ADMIN')" />
        <security:intercept-url pattern="/tasks"
            access="isAuthenticated() and hasRole('ROLE_USER')" />
        <security:intercept-url pattern="/tasks/*"
            access="isAuthenticated() and hasRole('ROLE_USER')" />

        <security:access-denied-handler ref="restAccessDeniedHandler" />

        <security:csrf disabled="true" />
    </security:http>
</beans>

(我已禁用 CSRF,因为它给 POSTMAN 客户端带来了一些问题。) 当用户输入用户名和密码并发送 JSON 时,我正在创建 token ,并在 header 中使用该 token ,我正在访问资源。它对我来说工作得很好,包括角色,除了一些事情。

这是我的处理程序。

身份验证入口点处理程序

@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException, ServletException {
//      response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        PrintWriter out = response.getWriter();
        out.print("{\"message\":\""+ authException.getMessage() + "\", \"access-denied\":true,\"cause\":\"SC_UNAUTHORIZED\"}");
        out.flush();
        out.close();
    }
}

访问被拒绝处理程序

@Component
public class RestAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException accessDeniedException) throws IOException, ServletException {
        // response.sendError(HttpServletResponse.SC_FORBIDDEN,
        // accessDeniedException.getMessage());
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        PrintWriter out = response.getWriter();
        out.print("{\"message\":\"" + accessDeniedException.getMessage()
                + "\", \"access-denied\":true,\"cause\":\"SC_FORBIDDEN\"}");
        out.flush();
        out.close();

    }
}

我有几个用于任务和人员的 Controller ,它运行良好并返回 JSON。

首先,我在用户身份验证方面遇到问题。

这是 Controller 中的身份验证方法

@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
    public String authenticate(@RequestBody User user, HttpServletRequest request) throws Exception {

        UserDetails userDetails = userService.loadUserByUsername(user.getUsername());
        String tokenString = TokenUtils.createToken(user);
        return tokenString;
    }

User.java

import java.util.Collection;
import java.util.Collections;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
public class User implements UserDetails {

    private String username;
    private String password;

    // getters and setters
    // overridden methods
}

如果我输入正确的用户名和错误的密码,它将创建并返回 token 。如果我仅输入错误的用户名,它将转到 RestAuthenticationEntryPoint 并使用 JSON 消息发回 401 错误。

如何使用配置文件中的用户名和密码在 Controller 方法中对用户进行身份验证?如果凭据错误,它应该使用自定义 JSON 发送 401 状态。

此外,如果任何 Controller 中发生任何异常,我应该能够使用 JSON 消息发送 500 错误。有没有通用的方法来发送错误响应和处理身份验证?

我知道可能存在身份验证失败处理程序。但在XML配置中,哪里提呢。除了 <security:form login/> 之外,我没有看到该选项但我没有使用它。

最佳答案

有关使用用户名和密码在 Controller 方法中验证用户的问题的答案。在 Controller 中,您使用自己的方法来获取用户身份验证详细信息,因此无法使用配置文件中的用户凭据来执行此操作因为您没有使用 Spring Securities 默认过滤器链。您可以使用默认设置来填充数据库中的这些用户,或更改 loadByUserName 的实现以硬编码这些用户。

关于java - Spring Security 4 - REST 身份验证失败和 Controller 异常处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33564422/

相关文章:

java - 简单问题 - 在 Java 中更改位

rest - Etag token 如何在 HTTP 中的条件 GET 中工作?

php - 从 Android 应用程序在线访问 MySQL 哪一个更好? RESTful Web 服务还是异步任务?

java - 请推荐将 apache lucene 与 MVC/spring web 应用程序集成的最佳实践

spring - 如何在不继承 spring-boot-starter-web 的情况下在 Spring Boot 中获取 ObjectMapper 实例?

java - 没有持久化或数据库表的 Spring Boot 实体

java - 设计咨询 : Choosing between Singleton, 工厂等

java.lang.ClassNotFoundException : android. 支持.v4.view.TintableBackgroundView

angularjs - 使用 Oauth2、Angular 和 yii2 REST 提供 protected 文件夹中的图像

java - 尝试使用 Spring Boot REST 从 POST 读取 JSON 字符串