Struts 2 + Spring + iBatis 기반 웹 응용 최 적 실천 시리즈 6 (인증 코드 편)

이 편 에 서 는 Struts 2 를 어떻게 사용 하여 일반적인 인증 코드 (checkcode) 기능 을 실현 하 는 지 에 대해 논의 합 니 다.
 
우선 우리 가 만 든 checkcode 를 저장 하기 위해 CheckCode Session 클래스 가 있어 야 합 니 다.이 종 류 는 매우 간단 합 니 다. 주로 인증 코드 자체, 생 성 시간 과 효과 적 인 표 지 를 저장 하 는 것 입 니 다.
 
public class CheckCodeSession {
	private String checkCode;//   
	private long createTime;//    
	private boolean validate = false;//    (    )
	public String getCheckCode() {
		return checkCode;
	}
	public void setCheckCode(String checkCode) {
		this.checkCode = checkCode;
	}
	public long getCreateTime() {
		return createTime;
	}
	public void setCreateTime(long createTime) {
		this.createTime = createTime;
	}
	public boolean isValidate() {
		return validate;
	}
	public void setValidate(boolean validate) {
		this.validate = validate;
	}
}

 
checkcode aciton 을 다시 보 겠 습 니 다.이 는 0 - 90 개의 숫자 중에서 랜 덤 으로 4 개 를 checkcode, 즉 인증 코드 자체 로 선택 하고 생 성 된 인증 코드 를 checkCodeSession 에 할당 하 며 유효 하 게 설정 합 니 다.Check CodeSession Aware 라 는 인터페이스 도 실현 했다.
public class CheckCodeAction implements Action, CheckCodeSessionAware {

	private static final long serialVersionUID = 1L;
	private String checkCode;
	private CheckCodeSession checkCodeSession;
	private int codeLenght = 4;
	private static char[] codes={'0','1','2','3','4','5','6','7','8','9'};
	public String execute() throws Exception {
		Random random = new Random();
		char[] checkCodeChararray = new char[codeLenght];
		for(int i=0;i<codeLenght;i++){
			checkCodeChararray[i] = codes[random.nextInt(codes.length)];
		}
		checkCode = String.valueOf(checkCodeChararray);
		checkCodeSession.setCheckCode(checkCode);
		
		checkCodeSession.setCreateTime(System.currentTimeMillis());
		checkCodeSession.setValidate(true);
		return SUCCESS;
	}

	public String getCheckCode() {
		return checkCode;
	}

	public void setCheckCodeSession(CheckCodeSession checkCodeSession) {
		this.checkCodeSession = checkCodeSession;
	}

	public void setCodeLenght(int codeLenght) {
		this.codeLenght = codeLenght;
	}

	public CheckCodeSession getCheckCodeSession() {
		return checkCodeSession;
	}
	
	
}

 
Check CodeSession Aware 인터페이스, 이 인 터 페 이 스 는 매우 간단 합 니 다. getter, setter 방법 은 두 개 밖 에 없습니다.
public interface CheckCodeSessionAware {
	public void setCheckCodeSession(CheckCodeSession checkCodeSession);
	public CheckCodeSession getCheckCodeSession();
}

 
현재 우 리 는 checkcode 와 checkcode 를 생 성 하 는 aciton 이 있 습 니 다. 그러면 구체 적 으로 검증 기능 을 어떻게 실현 합 니까?이것 은 Struts 2 의 검증 프레임 워 크 와 관련 되 어야 합 니 다. 우 리 는 코드 를 보고 CheckCodeSession Aware 인터페이스 와 결합 하여 CheckCodeValidator 가 checkcode 에 대한 검증 기능 을 실현 해 야 합 니 다.
public class CheckCodeValidator extends FieldValidatorSupport {
	private static Logger logger = Logger.getLogger(CheckCodeValidator.class);
	
	public void validate(Object object) throws ValidationException {
		Object obj = getFieldValue(getFieldName(), object);
		CheckCodeSession checkCodeSession = null;
		
		if(object instanceof CheckCodeSessionAware){
			checkCodeSession = ((CheckCodeSessionAware)object).getCheckCodeSession();
			if(checkCodeSession == null){
				logger.error("action: "+ object +" not implements CheckCodeSessionAware.class");
			}
		}
		
		String checkCode = (String) obj;
		if(StringUtil.isEmpty(checkCode) || checkCodeSession == null || !checkCodeSession.isValidate()){
			this.addFieldError(getFieldName(), object);
		}else{
			if(checkCode.equalsIgnoreCase(checkCodeSession.getCheckCode())){
				checkCodeSession.setValidate(false);
			}else{
				this.addFieldError(getFieldName(), object);
			}
		}
	}

 
Struts 2 프레임 워 크 는 매우 유연 하 게 설계 되 어 검증 자체 가 하나의 프레임 워 크 가 될 수 있 습 니 다. 우리 의 Check CodeValidator 는 FieldValidator Support 를 간단하게 계승 하면 하나의 vaidator 가 될 수 있 고 응용 프로그램 에서 간단 한 설정 만 하면 사용 할 수 있 습 니 다.
 
페이지 에 인증 코드 를 표시 하 는 방법 을 살 펴 보 겠 습 니 다. 여기 서 프레임 워 크 에 대한 확장 도 있 습 니 다. 저희 Check Code ResultType 은 StrutsResultSupport 를 계승 하여 새로운 result type 이 되 었 습 니 다.여기 서 자바 2d api 를 사용 하여 checkcode 의 값 에 따라 그림 을 만 든 후 http Response 에 직접 기록 합 니 다.주의해 야 할 것 은 http header 에 No - cache 방식 을 설정 한 것 입 니 다. 이것 은 브 라 우 저 캐 시 checkcode 그림 을 저장 하지 않도록 하기 위 한 것 입 니 다.
 
public class CheckCodeResultType extends StrutsResultSupport{
    protected String contentType = "image/jpeg";
    protected int contentLength;
    private String checkCode;
    
    
    /**
     * @return Returns the contentType.
     */
    public String getContentType() {
        return (contentType);
    }

    /**
     * @param contentType The contentType to set.
     */
    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    /**
     * @return Returns the contentLength.
     */
    public int getContentLength() {
        return contentLength;
    }

    /**
     * @param contentLength The contentLength to set.
     */
    public void setContentLength(int contentLength) {
        this.contentLength = contentLength;
    }



    /**
     * @see com.opensymphony.xwork.Result#execute(com.opensymphony.xwork.ActionInvocation)
     */
    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
        try {
            // Find the Response in context
            HttpServletResponse oResponse = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE);
            oResponse.setHeader("Pragma","No-cache");
            oResponse.setHeader("Cache-Control","no-cache");
            oResponse.setDateHeader("Expires", 0);

            // Set the content type
            oResponse.setContentType(conditionalParse(contentType, invocation));

            // Set the content length
            if (contentLength != 0) {
                 oResponse.setContentLength(contentLength);
            }
            // Get the outputstream
            OutputStream oOutput = oResponse.getOutputStream();
            
            //         (4   )
            String rand=conditionalParse(checkCode, invocation);
            
//                  
            int width=60, height=24;
            if(rand!= null){
            	width = 17 * rand.length();
            }
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//                    
            Graphics g = image.getGraphics();

//                 
            Random random = new Random();

//                  
            g.setColor(getRandColor(200,250));
            g.fillRect(0, 0, width, height);

//                
            Font font = new Font("Times New Roman",Font.BOLD,20);
            g.setFont(font);

//               
            g.setColor(getRandColor(20,50));
            g.drawRect(0,0,width-1,height-1);


//                 155    ,                  
            g.setColor(getRandColor(160,200));
            for (int i=0;i<155;i++)
            {
             int x = random.nextInt(width);
             int y = random.nextInt(height);
                    int xl = random.nextInt(12);
                    int yl = random.nextInt(12);
             g.drawLine(x,y,x+xl,y+yl);
            }
            
            if(rand != null){
	            for (int i=0;i<rand.length();i++){
	                //           
	                g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));//           ,          ,        
	                g.drawString(String.valueOf(rand.charAt(i)),15 * i + 7,17);
	            }
            }

//                 
            g.dispose();

//                    
            ImageIO.write(image, "JPEG", oResponse.getOutputStream());
            
            // Flush
            oOutput.flush();
        }
        finally {
        	
        }
    }
   private Color getRandColor(int fc,int bc){//          
        Random random = new Random();
        if(fc>255) fc=255;
        if(bc>255) bc=255;
        int r=fc+random.nextInt(bc-fc);
        int g=fc+random.nextInt(bc-fc);
        int b=fc+random.nextInt(bc-fc);
        return new Color(r,g,b);
        }

	public String getCheckCode() {
		return checkCode;
	}
	
	public void setCheckCode(String checkCode) {
		this.checkCode = checkCode;
	}
}

 
 지금 우리 가 필요 로 하 는 코드 가 모두 있 습 니 다. 그렇다면 구체 적 인 응용 에서 어떻게 사용 해 야 합 니까?
우선 struts. xml 에 checkcode aciton 을 설정 합 니 다.여기 result type 은 우리 가 정의 한 checkCode 형식 을 사용 합 니 다.
 
		<result-types>
			<result-type name="checkCode"
				class="com.meidusa.toolkit.web.common.resulttype.CheckCodeResultType" />
		</result-types>
		<action name="checkCode"
			class="com.meidusa.toolkit.web.common.action.CheckCodeAction">
			<result name="success" type="checkCode">
				<param name="contentType">image/jpeg</param>
				<param name="checkCode">${checkCode}</param>
			</result>
		</action>

 
그 다음 에 인증 코드 를 사용 해 야 하 는 aciton 에서 도 Check CodeSession Aware 인 터 페 이 스 를 실현 합 니 다. 예 를 들 어 우리 의 login aciton 입 니 다.
 
public class LoginAction extends ActionSupport implements	ClientCookieAware<Cookie>, ClientCookieNotCare, CheckCodeSessionAware{

	private Cookie cookie;
	private String loginId;
	private CheckCodeSession checkCodeSession;
	private String checkcode;
	
	public String getCheckcode() {
		return checkcode;
	}

	public void setCheckcode(String checkcode) {
		this.checkcode = checkcode;
	}

	public String getLoginId() {
		return loginId;
	}

	public void setLoginId(String loginId) {
		this.loginId = loginId;
	}

	public Cookie getCookie() {
		return cookie;
	}

	public void setClientCookie(Cookie cookie) {
		this.cookie = cookie;		
	}

	public String execute() throws Exception {
			cookie.setLoginId(loginId);
			cookie.save();
			return SUCCESS;

		}

	public CheckCodeSession getCheckCodeSession() {
		return checkCodeSession;
	}

	public void setCheckCodeSession(CheckCodeSession checkCodeSession) {
		this.checkCodeSession = checkCodeSession;
	}
}

 
 
여기, 아직 매우 중요 한 단계 가 있다.여러분 은 본문 첫머리 에 소 개 된 Check CodeSession 류 와 Check CodeSession Aware 인 터 페 이 스 를 기억 하 십 니까?CheckCodeSession Aware 인터페이스의 기능 은 struts 2 의 vaidation 프레임 워 크 가 vaidate 방법 을 호출 하여 검증 할 때 aciton 에서 CheckCodeSession 대상 을 얻 을 수 있 도록 하 는 것 외 에 도 중요 한 기능 은 spring 으로 하여 금 이 CheckCodeSession 대상 을 주입 하 게 하 는 것 이다.즉, Check CodeSession 은 하나의 bean 으로 spring 에서 설정 해 야 한 다 는 것 이다.여기 서 매우 중요 한 단 계 는 scope 를 session 으로 설정 하여 checkcode aciton 의 CheckCodeSession 과 checkcode 검증 이 필요 한 action (예 를 들 어 여기 login aciton) 의 CheckCodeSession 을 일치 시 키 는 것 입 니 다.세 션 으로 설정 되 어 있 지 않 으 면 인증 프레임 워 크 가 검증 할 때 읽 는 checkcode 값 은 사용자 가 입력 한 값 과 다 릅 니 다.
 
<bean id="checkCodeSession" class="com.meidusa.toolkit.web.common.components.CheckCodeSession" scope="session" />

 
이것 은 spring 2.0 의 프로필 을 사용 해 야 합 니 다. 오래된 버 전의 spring 프로필 은 scope 라 는 속성 을 지원 하지 않 습 니 다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

 
 마지막 으로, struts 2 프레임 워 크 에 우리 가 정의 한 추가 validator 를 알려 주 고, 이 파일 을 struts. xml 와 같은 디 렉 터 리 에 놓 아야 합 니 다.
 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//OpenSymphony Group//XWork Validator Config 1.0//EN"
         "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd"> 
<validators>  
   <validator name="checkcode"  class="com.meidusa.toolkit.web.common.validators.CheckCodeValidator"/> 
</validators> 

 
모든 것 이 설정 되 어 있 는 상황 에서 페이지 에서 checkcode 를 어떻게 사용 하 는 지 다시 한번 봅 시다.
<label>      </label><input type="text" name="checkcode" /><img src="/demo/checkCode.action"/></br><s:fielderror/>

 
마지막 으로, 우리 의 checkcode validator 를 우리 의 loginAction 에 설정 합 니 다.
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" 
       "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
       
<validators>
	<field name="checkcode">
		<field-validator type="requiredstring">
			<message>       </message>
		</field-validator>
		<field-validator type="checkcode">
			<message>      !</message>
		</field-validator>
	</field>
</validators>

 
이로써 인증 코드 의 실현 에 대해 모두 소 개 했 습 니 다. 이것 은 본 시리즈 의 여섯 번 째 편 입 니 다. 필 자 는 다음 편 에서 데 모 를 보 내 서 여러분 에 게 다운로드 체험 을 제공 하고 전체 시 리 즈 를 끝 낼 것 입 니 다.

좋은 웹페이지 즐겨찾기