Handle unauthorized error message for Basic Authentication in Spring Security

后端 未结 2 830
眼角桃花
眼角桃花 2020-12-04 18:25

I am trying to use Spring Security 3.0.5 in my web application. Basically, I want to have a web service which return data in json format via HTTP GET.

I

相关标签:
2条回答
  • 2020-12-04 18:59

    I have solved my problem so I think I should share it here. This configuration allows server to send out error message differently depending on the requesting software. If the request comes from a web browser, it will check the User-Agent header and redirect to a form login if necessary. If the request comes from, for example, curl, it will print out plain text error message when the authentication fails.

    <?xml version="1.0" encoding="UTF-8"?>
    <beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:sec="http://www.springframework.org/schema/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:p="http://www.springframework.org/schema/p"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
    
        <!-- AspectJ pointcut expression that locates our "post" method and applies security that way
        <protect-pointcut expression="execution(* bigbank.*Service.post*(..))" access="ROLE_TELLER"/>-->
        <sec:global-method-security secured-annotations="enabled"/>
    
        <bean id="basicAuthenticationFilter"
              class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter"
              p:authenticationManager-ref="authenticationManager"
              p:authenticationEntryPoint-ref="basicAuthenticationEntryPoint" />
    
        <bean id="basicAuthenticationEntryPoint"
              class="webapp.PlainTextBasicAuthenticationEntryPoint"
              p:realmName="myWebapp"/>
    
        <bean id="formAuthenticationEntryPoint"
              class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"
              p:loginFormUrl="/login.jsp"/>
    
        <bean id="daep" class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
            <constructor-arg>
                <map>
                    <entry key="hasHeader('User-Agent','Mozilla') or hasHeader('User-Agent','Opera') or hasHeader('User-Agent','Explorer')" value-ref="formAuthenticationEntryPoint" />
                </map>
            </constructor-arg>
            <property name="defaultEntryPoint" ref="basicAuthenticationEntryPoint"/>
        </bean>
    
        <sec:http entry-point-ref="daep">
            <sec:intercept-url pattern="/login.jsp*" filters="none"/>
            <sec:intercept-url pattern="/json" access="ROLE_USER,ROLE_ADMIN"  />
            <sec:intercept-url pattern="/json/*" access="ROLE_USER,ROLE_ADMIN"  />
            <sec:logout
                logout-url="/logout"
                logout-success-url="/home.jsp"/>
            <sec:form-login
                login-page="/login.jsp"
                login-processing-url="/login"
                authentication-failure-url="/login.jsp?login_error=1" default-target-url="/home.jsp"/>
            <sec:custom-filter position="BASIC_AUTH_FILTER" ref="basicAuthenticationFilter" />
        </sec:http>
    
        <sec:authentication-manager alias="authenticationManager">
            <sec:authentication-provider>
            ...
            </sec:authentication-provider>
        </sec:authentication-manager>
    
    </beans>
    

    PlainTextBasicAuthenticationEntryPoint by extending org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint

    import java.io.IOException;
    import java.io.PrintWriter;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
    
    public class PlainTextBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
    
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
            response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\"");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            PrintWriter writer = response.getWriter();
            writer.println("HTTP Status " + HttpServletResponse.SC_UNAUTHORIZED + " - " + authException.getMessage());
        }
    }
    
    0 讨论(0)
  • 2020-12-04 19:08

    I am wondering if it is ever making it to your AccessDeniedHandler. Is the error because of Authentication or Authorization? Does the AccessDeniedHandeler get called for both scenarios? I am in the process of solving this myself right now.

    0 讨论(0)
提交回复
热议问题