即使它们是正确的,弹簧安全性也是不好的

时间:2014-05-20 13:11:39

标签: spring spring-mvc spring-security spring-roo sha

我正在使用Spring Roo,我设置了我的Spring Security(applicationContext-security.xml):

<?xml version="1.0" encoding="UTF-8"?>
<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-3.1.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    <!-- HTTP security configurations -->
    <http auto-config="true" use-expressions="true" request-matcher="regex">
        <form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" />
        <logout logout-url="/resources/j_spring_security_logout" />
        <intercept-url pattern="\A/hotels\?form.*\Z" access="hasRole('ROLE_ADMIN')"/>
        <intercept-url pattern="/**" access="permitAll"/>
    </http>
    <!-- Configure Authentication mechanism -->
    <authentication-manager alias="authenticationManager">
        <!-- SHA-256 values can be produced using 'echo -n your_desired_password | sha256sum' (using normal *nix environments) -->
        <authentication-provider>
            <password-encoder hash="sha-256">
                <!-- <salt-source user-property="login"/> -->
            </password-encoder>
            <jdbc-user-service data-source-ref="dataSource"
                users-by-username-query="
                SELECT login, password, enabled
                FROM user WHERE login = ?"

                authorities-by-username-query="
                FROM user u, role r, 
                user_role ur
                WHERE u.id = ur.user
                AND r.id = ur.role
                AND u.login = ?"        
            />
            <user-service>
                <user name="admin" password="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918" authorities="ROLE_ADMIN" />
                <user name="user" password="04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
</beans:beans>

然后我创建了一个虚拟用户,其登录名为johnny,密码为admin,存储在数据库中,如8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918

这是框架提供的默认登录页面:

<div xmlns:spring="http://www.springframework.org/tags" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:util="urn:jsptagdir:/WEB-INF/tags/util" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
  <jsp:directive.page contentType="text/html;charset=UTF-8" />
  <jsp:output omit-xml-declaration="yes" />
  <spring:message code="security_login_title" var="title" htmlEscape="false" />
  <util:panel id="title" title="${title}">
    <c:if test="${not empty param.login_error}">
      <div class="errors">
        <p>
          <spring:message code="security_login_unsuccessful" />
          <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
          .
        </p>
      </div>
      <br/>
    </c:if>
    <c:if test="${empty param.login_error}">
      <p>
        <!-- <spring:message code="security_login_message" /> -->
      </p>
    </c:if>
    <spring:url value="/resources/j_spring_security_check" var="form_url" />
    <form name="f" action="${fn:escapeXml(form_url)}" method="POST">
      <input type="hidden" name="test"/>
      <div>
        <label for="j_username">
          <spring:message code="security_login_form_name" />
        </label>
        <input id="j_username" type='text' name='j_username' style="width:150px" />
        <spring:message code="security_login_form_name_message" var="name_msg" htmlEscape="false" />
        <script type="text/javascript">
          <c:set var="sec_name_msg">
            <spring:escapeBody javaScriptEscape="true">${name_msg}</spring:escapeBody>
          </c:set>
          Spring.addDecoration(new Spring.ElementDecoration({elementId : "j_username", widgetType : "dijit.form.ValidationTextBox", widgetAttrs : {promptMessage: "${sec_name_msg}", required : true}})); 
        </script>
      </div>
      <br />
      <div>
        <label for="j_password">
          <spring:message code="security_login_form_password" />
        </label>
        <input id="j_password" type='password' name='j_password' style="width:150px" />
        <spring:message code="security_login_form_password_message" var="pwd_msg" htmlEscape="false" />
        <script type="text/javascript">
          <c:set var="sec_pwd_msg">
            <spring:escapeBody javaScriptEscape="true">${pwd_msg}</spring:escapeBody>
          </c:set>
          Spring.addDecoration(new Spring.ElementDecoration({elementId : "j_password", widgetType : "dijit.form.ValidationTextBox", widgetAttrs : {promptMessage: "${sec_pwd_msg}", required : true}})); 
        </script>
      </div>
      <br />
      <div class="submit">
        <script type="text/javascript">Spring.addDecoration(new Spring.ValidateAllDecoration({elementId:'proceed', event:'onclick'}));</script>
        <spring:message code="button_submit" var="submit_label" htmlEscape="false" />
        <input id="proceed" type="submit" value="${fn:escapeXml(submit_label)}" />
        <spring:message code="button_reset" var="reset_label" htmlEscape="false" />
        <input id="reset" type="reset" value="${fn:escapeXml(reset_label)}" />
      </div>
    </form>
  </util:panel>
</div>

但是,当我尝试登录时,出现Bad credentials错误。发生了什么事?

我无法真正设法找到一种如何调试它的方法,因为它在Spring安全内部发生了所有我想我无法知道实际上是在做什么查询而且我无法知道在哪里找出失败的原因。

2 个答案:

答案 0 :(得分:1)

当您尝试以用户身份进行身份验证时,请查看调试日志输出(总是一个好主意)。很可能它说它无法找到用户&#34; johnny&#34;。

这很可能是因为您在同一个jdbc-user-service中同时拥有user-serviceauthentication-provider,但

使用两个单独的authentication-provider元素:

<authentication-provider>
    <jdbc-user-service ... />
</authentication-provider>
<authentication-provider>
    <user-service>
       ....
    </user-service>
</authentication-provider>

另外,正如我在你的另一个问题中所说,你不应该使用SHA作为密码散列算法,除非它适用于遗留系统。

答案 1 :(得分:0)

经历了更多的痛苦后,我设法解决了这个问题。我再次创建了用户和角色实体表并重新编写了查询:

        <jdbc-user-service data-source-ref="dataSource"
        users-by-username-query="SELECT u.login, u.password, u.enabled from users u where u.login=?"
        authorities-by-username-query="SELECT u.login, r.name FROM users u left join user_roles ur on u.id=ur.user join roles r on ur.roles=r.id WHERE u.login=?" 
        />

使用两个separte authentication-provide与我的错误无关。