如何在Spring Security中为REST API调用返回401?

moh*_*han 5 spring spring-security

以下是我的示例Spring Security配置。

我希望所有人/api返回HTTP 401代码,而不是将302重定向到登录页面。

我也想保留旧网页的重定向功能。

<security:http auto-config='true' use-expressions="true" >
    <security:intercept-url pattern="/api*" access="hasRole('USER')" />
    <security:intercept-url pattern="/oldweb*" access="hasRole('USER')" />

    <security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" default-target-url="/home"/>    
</security:http>
Run Code Online (Sandbox Code Playgroud)

Ole*_*_DJ 8

我想到了更简单的解决方案。在Spring Boot和Java config中,您只需注册默认入口之外的其他入口点即可。而且,由于所有其余服务都位于“ / api”名称空间中,因此您可以使用它AntPathRequestMatcher("/api/**")来匹配必要的请求。

因此,最终的解决方案是:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http.exceptionHandling()
                    //Actually Spring already configures default AuthenticationEntryPoint - LoginUrlAuthenticationEntryPoint
                    //This one is REST-specific addition to default one, that is based on PathRequest
                    .defaultAuthenticationEntryPointFor(getRestAuthenticationEntryPoint(), new AntPathRequestMatcher("/api/**"));
    }

    private AuthenticationEntryPoint getRestAuthenticationEntryPoint() {
        return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED);
    }
}
Run Code Online (Sandbox Code Playgroud)


Mon*_*mul 5

您需要有一个自定义身份验证入口点。

public class CustomEntryPoint extends LoginUrlAuthenticationEntryPoint {

    private static final String XML_HTTP_REQUEST = "XMLHttpRequest";
    private static final String X_REQUESTED_WITH = "X-Requested-With";

    public CustomEntryPoint(String loginFormUrl) {
        super(loginFormUrl);
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException {
        if (XML_HTTP_REQUEST.equals(request.getHeader(X_REQUESTED_WITH))) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        } else {
            super.commence(request, response, exception);
        }
    }    
}
Run Code Online (Sandbox Code Playgroud)

最后将您的配置更改为:

<security:http auto-config='true' use-expressions="true" entry-point-ref="customEntryPoint">
    <security:intercept-url pattern="/api*" access="hasRole('USER')" />
    <security:intercept-url pattern="/oldweb*" access="hasRole('USER')" />

    <security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" default-target-url="/home"/>

    <beans:bean id="customEntryPoint" class="CustomEntryPoint">
        <beans:constructor-arg value="/login"/>
    </beans:bean>    
</security:http>
Run Code Online (Sandbox Code Playgroud)