【问题标题】:Spring Security 4 - REST Authentication Failure and Controller Exception handlersSpring Security 4 - REST 身份验证失败和控制器异常处理程序
【发布时间】:2016-02-07 11:02:40
【问题描述】:

我正在通过一些示例应用程序学习 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 时,我正在创建令牌,并在标头中使用该令牌,我正在访问资源。它对我来说很好,包括角色,除了几件事。

这是我的处理程序。

身份验证入口点处理程序

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

    }
}

我的任务和人员控制器很少,它运行良好并返回 JSON。

首先我的用户身份验证有问题。

这是控制器中的身份验证方法

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

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

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

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

我知道可以有身份验证失败处理程序。但是在 XML 配置中,哪里不提了。除了&lt;security:form login/&gt; 之外,我没有看到该选项,但我没有使用它。

【问题讨论】:

  • 请一次一个问题。

标签: java rest spring-mvc spring-security


【解决方案1】:

关于authenticate user in controller method with username and password的问题的答案。在控制器中,您使用自己的方法来获取用户身份验证详细信息,您不能使用配置文件中的用户凭据来执行此操作。因为您没有使用弹簧证券默认过滤器链。您可以使用默认设置将这些用户填充到数据库中,或者更改 loadByUserName 的实现以对这些用户进行硬编码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 2015-05-30
    • 2022-08-16
    • 1970-01-01
    相关资源
    最近更新 更多