spring security 3.1認証コードのカスタム登録を実現します.


spring securityカスタム登録:
1、カスタムテーブル構造
Tシャツ.US ER:(ユーザ表)
`id`bigintt(11)NOT NULL AUTO_INCREMENT、
`name`varrhar
`password`varhar
 
Tシャツ.ROLE:(キャラクター表)
`id`bigintt(11)NOT NULL AUTO_INCREMENT、
`role`varrhar--キャラクター名(spring security定義キャラクター名はROLE_で始まる)
 
Tシャツ.USER_ROLE:(ユーザーキャラクター関連表)
`id`bigintt(11)NOT NULL AUTO_INCREMENT、
`user_id`bigint(11)
`role_id`bigint(11)
 
2、必要なjarバッグ:
spring-security-acl-3.1.0.RC.jar
spring-security-aspects-3.1.0.RC.jar
spring-security-cas-3.1.0.RC.jar
spring-security-config-3.1.0.RC.jar
spring-security-coree-3.1.0.RC.jar
spring-security-ldp-3.1.0.RC.jar
spring-security-openid-3.1.0.RC.jar
spring-security-taglibs-3.1.0.RC 2.jar
spring-security-web-3.1.0.RC.jar
 
3、ログインページのlogin.jsp
<form id="loginForm"
    action="<c:url value='/j_spring_security_check'/>" method="post">
    <table width="100%" border="0" cellspacing="0" cellpadding="0">
     <tr>
      <th>   :</th>
      <td><input type="text" name="j_username" id="username"
       class="input"
       value="<c:if test='${not empty param.login_error}' > 
               <c:out value='${SPRING_SECURITY_LAST_USERNAME}'/>
               </c:if>" />
      </td>
      <td rowspan="3"><a onclick="javascript:login();"><img
        src="../img/home/login_btn.gif" width="111" height="99" /> </a></td>
     </tr>
     <tr>
      <th> &nbsp;&nbsp;&nbsp;&nbsp;  :</th>
      <td><input type="password" name="j_password" id="password"
       class="input" /></td>
     </tr>
     <tr>
      <th>   :</th>
      <td><input type="text" maxlength="4" name="code" id="code"
       class="input" style="width: 80px;" onkeypress="javascript:pressKey(event);" /> <img id="validateCode"
       src="validate.code" width="75" height="33" /> <a
       onclick="javascript:reload();"><img
        src="../img/home/refresh.gif" width="22" height="22" /> </a>
      </td>
     </tr>
    </table>
   </form>
   <c:if test="${not empty param.error}">
    <font color="red">     <br /> <br />   : <c:out
      value="${SPRING_SECURITY_LAST_EXCEPTION.message}" /></font>
   </c:if>
 
 
 
4、appication-security.xml配置
 
<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns="http://www.springframework.org/schema/security"
 xmlns:b="http://www.springframework.org/schema/beans" 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.0.xsd 
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

 <http>
  <!--     -->
  <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY" />

  <intercept-url pattern="/list/**"
   access="ROLE_ADMIN,ROLE_MANAGER,ROLE_USER" />

    <intercept-url pattern="/delete/**" access="ROLE_ADMIN" />

   <!--         -->
  <custom-filter before="FORM_LOGIN_FILTER" ref="validateCodeAuthenticationFilter" />

  <!--        -->
  <form-login login-page="/home/login"
   default-target-url="/home/loginSuccess.action"(     url)
   authentication-failure-url="/home/login.action?error=true"(     url) />

  <!--             -->
  <!-- <logout logout-success-url="/loggedout.jsp" delete-cookies="JSESSIONID"
   /> <remember-me /> -->

  <!-- SESSION          -->
  <!-- <session-management invalid-session-url="/timeout.jsp"> </session-management> -->
 </http>

 <authentication-manager alias="authenticationManager">
  <authentication-provider>
   <!--     SQL            , users-by-username-query:           authorities-by-username-query:        (            , t_user_role      )
    group-authorities-by-username-query:             -->
   <jdbc-user-service data-source-ref="webDataSource"
    users-by-username-query="SELECT t_user.name AS username,t_user.password as password,'true' AS enabled FROM t_user WHERE t_user.name = ?"
    authorities-by-username-query="SELECT name AS username,role as authorities
                               FROM T_USER
                               LEFT OUTER JOIN t_role AS userrole ON(t_user.id = userrole.user_id) 
                               LEFT OUTER JOIN t_role AS role ON (userrole.role_id = role.id) 
                               WHERE t_user.name = ?" />
  </authentication-provider>
 </authentication-manager>

 <!--        -->
 <beans:bean id="validateCodeAuthenticationFilter"
  class="**.**.security.ValidateCodeUsernamePasswordAuthenticationFilter">
  <beans:property name="authenticationSuccessHandler"
   ref="loginLogAuthenticationSuccessHandler"></beans:property>
  <beans:property name="authenticationFailureHandler"
   ref="simpleUrlAuthenticationFailureHandler"></beans:property>
  <beans:property name="authenticationManager" ref="authenticationManager"></beans:property>
 </beans:bean>

 <!--      -->
 <beans:bean id="loginLogAuthenticationSuccessHandler"
  class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
  <beans:property name="defaultTargetUrl" value="/home/loginSuccess.action"></beans:property>
 </beans:bean>

 <!--      -->
 <beans:bean id="simpleUrlAuthenticationFailureHandler"
  class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
  <beans:property name="defaultFailureUrl" value="/home/login.action?error=true"></beans:property>
 </beans:bean>

</beans:beans> 
 
5、検証コードの検証
package cn.com.trade.security;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.TextEscapeUtils;

import cn.com.fxark.util.md5.MD5;
import cn.com.trade.domain.adminuser.AdminUser;
import cn.com.trade.global.GlobalParameter;
import cn.com.trade.service.ServiceManager;

/**
 *             、       
 * 
 *         ;          。
 * 
 * @author Long
 * 
 */
public class ValidateCodeUsernamePasswordAuthenticationFilter extends
		UsernamePasswordAuthenticationFilter {

	private boolean postOnly = true;
	private boolean allowEmptyValidateCode = false;
	private String sessionvalidateCodeField = DEFAULT_SESSION_VALIDATE_CODE_FIELD;
	private String validateCodeParameter = DEFAULT_VALIDATE_CODE_PARAMETER;
	public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
	// session       
	public static final String DEFAULT_SESSION_VALIDATE_CODE_FIELD = "rand";
	//       
	public static final String DEFAULT_VALIDATE_CODE_PARAMETER = "code";

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		if (postOnly && !request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException(
					"Authentication method not supported: "
							+ request.getMethod());
		}

		String username = obtainUsername(request);
		String password = obtainPassword(request);

		if (username == null) {
			username = "";
		}

		if (password == null) {
			password = "";
		}

		username = username.trim();

		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
				username, password);

		// Place the last username attempted into HttpSession for views
		HttpSession session = request.getSession(false);

		if (session != null || getAllowSessionCreation()) {
			request.getSession().setAttribute(
					SPRING_SECURITY_LAST_USERNAME_KEY,
					TextEscapeUtils.escapeEntities(username));
		}

		// Allow subclasses to set the "details" property
		setDetails(request, authRequest);
		// check validate code
		if (!isAllowEmptyValidateCode())
			checkValidateCode(request);
		//          
		AdminUser adminUser = ServiceManager.getInstance()
				.getAdminUserService()
				.login(username, MD5.getMD5ofStr(password));
		session.setAttribute(GlobalParameter.HT_ADMIN_LOGIN_USER_SESSION_NAME,
				adminUser);
		return this.getAuthenticationManager().authenticate(authRequest);
	}

	/**
	 * 
	 * <li>  session                  </li>
	 * 
	 */
	protected void checkValidateCode(HttpServletRequest request) {
		String sessionValidateCode = obtainSessionValidateCode(request);
		String validateCodeParameter = obtainValidateCodeParameter(request);
		if (StringUtils.isEmpty(validateCodeParameter)
				|| !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {
			throw new AuthenticationServiceException("     !");
		}
	}

	private String obtainValidateCodeParameter(HttpServletRequest request) {
		return request.getParameter(validateCodeParameter);
	}

	protected String obtainSessionValidateCode(HttpServletRequest request) {
		Object obj = request.getSession()
				.getAttribute(sessionvalidateCodeField);
		return null == obj ? "" : obj.toString();
	}

	public boolean isPostOnly() {
		return postOnly;
	}

	@Override
	public void setPostOnly(boolean postOnly) {
		this.postOnly = postOnly;
	}

	public String getValidateCodeName() {
		return sessionvalidateCodeField;
	}

	public void setValidateCodeName(String validateCodeName) {
		this.sessionvalidateCodeField = validateCodeName;
	}

	public boolean isAllowEmptyValidateCode() {
		return allowEmptyValidateCode;
	}

	public void setAllowEmptyValidateCode(boolean allowEmptyValidateCode) {
		this.allowEmptyValidateCode = allowEmptyValidateCode;
	}

}