spring security自定义身份验证无效

时间:2017-04-04 11:26:03

标签: java spring spring-mvc spring-security

我正在运行一个基于Spring安全性版本4.2,spring mvc 4.2版的Web应用程序。我想运行 customAuthenticationProvider customAuthenticationSuccessHandler ,但是没有调用customAuthenticationProvider类,而且只有 authentication-failure-url

的pom.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

    <http pattern="/resources/css/**" security="none"/>
    <http pattern="/resources/img/**" security="none"/>
    <http pattern="/resources/js/**" security="none"/>



    <http auto-config="false" use-expressions="true"> 
<!--    <intercept-url pattern="/onemoretime/*" access="hasRole('ROLE_ADMIN')"/>-->
        <intercept-url pattern="/admin/*" access="permitAll"/>
        <intercept-url pattern="/vendor/*" access="permitAll"/>
        <form-login login-page="/login"         
                    username-parameter="username"
                    password-parameter="password"
                    authentication-success-handler-ref="customAuthenticationSuccessHandler"
                    authentication-failure-url="/accessdenied"
                    />

        <!-- <logout logout-success-url="/login"/>       -->    
         <csrf />
    </http>

    <authentication-manager alias="authenticationProvider">
        <authentication-provider ref="myAuthenticationProvider"/> 

    </authentication-manager>

    <!-- Bean implementing AuthenticationProvider of Spring Security -->
    <beans:bean id="myAuthenticationProvider" class="com.opstree.vendorportal.authentication.CustomAuthenticationProvider"/>

    <beans:bean id="customAuthenticationSuccessHandler" class="com.opstree.vendorportal.authentication.CustomAuthenticationSuccess"/>

</beans:beans>

应用的security.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:/service.xml /WEB-INF/application-security.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

的web.xml

    <form action="${pageContext.request.contextPath}/login" method="post">
        <table>
            <tr>
                <td>UserName</td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><input type="password" name="password"> </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <div style="color:red" class="servererror">
                        <c:if test="${not empty userobject}">
                            <b><c:out value="${userobject.message}"></c:out></b>
                        </c:if>
                    </div>
                </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <input type="submit" value="Login">
                </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <b><a href="forgotpassword">ForgotPassword</a></b>
                </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <b>Click here to <a href="registerVendor">Register</a></b>
                </td>
            </tr>
        </table>
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    </form>

loginpage.jsp

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDBOperationsImpl userDAO;

    private Logger logger = Logger.getLogger(getClass());

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        System.out.println("Spring Security: Entered");
        UsernamePasswordAuthenticationToken  authenticationToken = (UsernamePasswordAuthenticationToken) authentication;
        String username = authenticationToken.getName();
        //String password = (String) authenticationToken.getCredentials();

        UserBean userBean = null;

        try {
            userBean =  userDAO.getUserDetails(username);
        } catch (Exception e) {
            logger.error(e.getCause().getMessage());
        }

        if(userBean == null){
            throw new BadCredentialsException("Invalid Credentials");
        }
        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

        Authentication auth = new UsernamePasswordAuthenticationToken(userBean, userBean.getPassword(), authorities);

        System.out.println("Exit");
        return auth;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(getClass());
    }

customAuthenticationProvider

public class CustomAuthenticationSuccess implements AuthenticationSuccessHandler {

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth)
            throws IOException, ServletException {
        System.out.println("Entered Authentication Successful Method");
        boolean isUser = false;
        Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
        String targetUrl = null;
        for(GrantedAuthority currentAuth : authorities){
            if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){
                isUser = true;
                break;
            }
            else {
                throw new IllegalStateException();
            }
        }

        if(isUser){
            targetUrl = "/vendor";
        }
        System.out.println("Entered Authentication Successful Method");
        redirectStrategy.sendRedirect(request, response, targetUrl);
    }
}

customAuthenticationSuccess

 Public Class Demo
    {
    public Demo()
            {
        var connection = new HubConnection("http://localhost:47315/")
                        {
                            CookieContainer = new CookieContainer()
                        };
        connection.CookieContainer.Add(GetAuthCookie("user1", "pass"));
 chatHubProxy = connection.CreateHubProxy("servicesSatatuseHub");
                 connection.Start().Wait();
     }

    private static System.Net.Cookie GetAuthCookie(string user, string pass)
            {
                //var http = WebRequest.Create("http://localhost:47315/module/account/login.aspx") as HttpWebRequest;
                var http = WebRequest.Create("http://localhost:47315//module/account/login.aspx") as HttpWebRequest;
                http.AllowAutoRedirect = false;
                http.Method = "POST";
                http.ContentType = "application/x-www-form-urlencoded";
                http.CookieContainer = new CookieContainer();
                //var postData = "UserName=" + user + "&Password=" + pass + "";
                var postData = "UserName=" + user + "&Password=" + pass + "";
                byte[] dataBytes = System.Text.Encoding.UTF8.GetBytes(postData);
                http.ContentLength = dataBytes.Length;
                using (var postStream = http.GetRequestStream())
                {
                    postStream.Write(dataBytes, 0, dataBytes.Length);
                }
                System.Net.Cookie authCookie;
                using (var response = http.GetResponse() as HttpWebResponse)
                {
                    authCookie = response.Cookies[FormsAuthentication.FormsCookieName];//authCookie = null
                }

                httpResponse.Close();
                return cookie;
            }
}

1 个答案:

答案 0 :(得分:1)

我认为发生的情况是supports(Class<?> authentication)中的AuthenticationProvider方法未正确实施。

您正在检查已根据Authentication CustomAuthenticationProvider方法收到的getClass()课程,因此总是会返回false,AuthenticationManager将无法将您的提供者视为合适的已收到UsernamePasswordAuthenticationToken的提供商。

您可以在github中检查org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider代码,您可以在UsernamePasswordAuthenticationToken支持提供商中看到此方法的正确实现应该是这样的:

public boolean supports(Class<?> authentication) {
    return (UsernamePasswordAuthenticationToken.class
            .isAssignableFrom(authentication));
}

我猜实际发生的事情是AuthenticationManager无法找到UsernamePasswordAuthenticationToken支持提供商,因此无法执行身份验证,未经授权的Authentication将转到UsernamePasswordAuthenticationFilter最终无关,但重定向到authentication-failure-url

使用AuthenticationSuccessHandler时也要小心,如果第一个GranthedAuthorities评估的IllegalStateException不是GranthedAuthority,那么ROLE_USER检查的方式可能会以 for(GrantedAuthority currentAuth : authorities){ if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){ isUser = true; break; } else { throw new IllegalStateException(); } } 结尾一个:

Perl