2013년 8월 11일 일요일

Struts를 이용한 인증 예제_비즈니스 로직분리,Custom Tag 사용

이번 예제는 이전 로그인 예제의 기능을 개선한 예제인데 바뀐 부분은 아래와 같습니다.

(Struts 1.3.8에서 작성 했습니다.)

오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷 실무전문 강의)  



1. 사용자가 main.jsp를 호출 하면 인증을 하지 않은 사용자는 자동으로 login.jsp로 보내어 버립니다. 물론 인증을 이미 한 사용자라면 환영 인사와 로그아웃을 활성화 합니다.



2. main.jsp에서 인증이 되었는지 안되었는지의 여부는 사용자 정의 태그(Custom Tag Library)를 이용하였으며 중추적인 역할을 하는 Tag Handler 클래스는 IsLogin.java 입니다.



3. login.jsp, main.jsp 에서 화면 UI의 구성을 위해 화면에 뿌리는 텍스트 등을 message 처리 했습니다.(application.properties)



4. 기존 예제의 LoginAction에 있던 인증 기능을 LoginDAO.java라는 Model을 이용하여 처리 했으며 인증이 성공적으로 끝난 후 사용자의 정보를 UserInfoVO라는 자바 빈에 저장 해 놓고 이를 이용 하였습니다. (비즈니스 로직을 분리 했습니다.)


















----------------

1. main.jsp

----------------



<%@ page language="java" %>

<%@ page pageEncoding="euc-kr" %>





<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>

<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>

<%@ taglib uri="/WEB-INF/app.tld" prefix="login" %>






















반갑습니다.님!








  • 로그아웃



















-------------

2. login.jsp

-------------



<%@ page pageEncoding="euc-kr" %>

<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>



























































































--------------------------------------------------

3. application.properties (/WEB-INF/src/resources/ 에 위치)

--------------------------------------------------





login.title = LogIn

login.login = Login

login.reset = Cancel



prompt.id= User ID :

prompt.password=Password :



main.title=Main





###############################################3

error.id.required=
  • ID REQUIRED.


  • error.pwd.required=
  • PASSWORD REQUIRED


  • error.login.invalid=
  • ID/PASSWORD NOT CORRECT




  • errors.header=

    ERROR!



    You must correct the following error(s) before proceeding:


      errors.footer=







    -----------------------------

    4. LoginForm.java (폼빈)

    -----------------------------



    package login3;



    import javax.servlet.http.HttpServletRequest;



    import org.apache.struts.action.ActionErrors;

    import org.apache.struts.action.ActionMessage;

    import org.apache.struts.action.ActionForm;

    import org.apache.struts.action.ActionMapping;



    public class LoginForm extends ActionForm {

    private String id=null;

    private String pwd=null;





    public String getId() {

    return id;

    }



    public String getPwd() {

    return pwd;

    }



    public void setId(String id) {

    this.id = id;

    }



    public void setPwd(String pwd) {

    this.pwd = pwd;

    }



    /* struts-config.xml 에서 메핑시 validate="true" 라고 설정 되면 아래의

    validate 함수가 호출 되어 입력되는 값에 대한 validation check를 하게 됩니다.

    HTTP 요청으로 부터 해당 폼의 값을 set 한 후 아래 메소드가 호출 됩니다.

    참고로 validate에 위해 반환되는 ActionErrors 객체 역시 Framework에 관련된 클래스 입니다.

    만약 validate에서 null이나 empty가 아닌 ActionError 객체를 리턴하게 되면

    login.jsp에 있는 태그는 오류를 출력하고 아니면 넘어가게 됩니다...

    error.id.required, error.pwd.required는 일종의 키값으로 각 Locale마다 고유한 리소스를 가질 수

    있으므로 메시지에 대해 손쉬운 관리를 제공 합니다.

    예를들면 error.id.required = 사용자 ID는 필수 입력 항목 입니다. , 이러한 식으로 설정 합니다.

    */



    public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {

    ActionErrors errors = new ActionErrors();



    if((id == null) || (id.length()<1)) {

    errors.add("error.id.required", new ActionMessage("error.id.required"));

    }



    if((pwd == null) || (pwd.length()<1)) {

    errors.add("error.pwd.required", new ActionMessage("error.pwd.required"));

    }



    return errors;

    }









    }





    -------------------------------

    5. LoginAction.java(Action)

    -------------------------------



    package login3;



    import org.apache.struts.action.Action;

    import java.io.IOException;

    import javax.servlet.ServletException;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpSession;

    import javax.servlet.http.HttpServletResponse;



    import login2.LoginForm;

    import login2.Constants;



    import org.apache.struts.action.Action;

    import org.apache.struts.action.ActionErrors;

    import org.apache.struts.action.ActionMessage;

    import org.apache.struts.action.ActionForm;

    import org.apache.struts.action.ActionMapping;

    import org.apache.struts.action.ActionForward;

    import org.apache.struts.action.ActionServlet;



    /**

    * @author 이종철

    */

    public class LoginAction extends Action {



    public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) {

    String id = ((LoginForm)form).getId();

    String pwd = ((LoginForm)form).getPwd();



    //Model을 이용하기 이용하여 인증부분의 처리를 합니다.

    LoginDAO loginDAO = new LoginDAO();

    UserInfoVO userinfo = loginDAO.authUser(id, pwd);



    //에러 내용을 담을 ActionErrors 객체를 생성

    ActionErrors errors = new ActionErrors();



    if (userinfo==null) {

    //인증 실패

    errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("error.login.invalid"));

    }

    else {

    //사용자 아이디와 비밀번호가 틀릴경우 비밀번호가 틀리다는 에러 메세지 출력

    if ( !id.equals(userinfo.getPwd()) ) {

    errors.add(ActionErrors.GLOBAL_MESSAGE,new ActionMessage("error.login.invalid"));

    }

    }



    //로그인 과정에서 에러가 있을 경우 Action클래스의 saveErrors 메소드를 이용해 에러를 저장하고

    //이전의 로그인 페이지로 돌려 보내면 login.jsp의 태그에 의해 오류가 출력됨

    //mapping의 getInputForward()에서 반환하게 되는 정보는 struts-config.xml의 action태그의

    //input 속성에 정의된 페이지로 이동하게 됩니다.

    if (!errors.isEmpty()) {

    saveErrors(request, errors);

    return (mapping.getInputForward());

    }



    //인증 성공한 경우 세션에 UserInfoVO(로그인한 사용자 정보를 담은 객체)저장

    HttpSession session = request.getSession();

    session.setAttribute(Constants.USER_KEY, userinfo);



    //로그를 남기자.

    StringBuffer buf = new StringBuffer("LoginAction : User --> ");

    buf.append(id + "logged in session");

    servlet.log(buf.toString());



    return (mapping.findForward(Constants.SUCCESS));



    }





    }





    -------------------------------------------------------------------

    6. LoginDAO.java (인증을 하기 위한 비즈니스 로직을 담고 있는 Model)

    -------------------------------------------------------------------



    package login3;



    public class LoginDAO {



    public UserInfoVO authUser(String id, String pwd) {

    /**

    * 이부분은 실제 DB에서 ID와 PASWORD로 인증을 해야 하는 부분 입니다.

    * 예제를 간략히 하기 위해 이 부분의 처리는 생략 했으며 ID가 "jclee", Password가 "jclee" 인 경우엔

    * 인증을 허용 합니다.

    */



    if ( id.equals("jclee")&& pwd.equals("jclee")) {

    //ID:jclee, PASSWORD:jclee인 경우 인증이 성공, 사용자의 정보(아이디, 패스워드)를 저장 합니다.

    return new UserInfoVO(id, pwd);

    } else {

    return null;

    }

    }

    }





    -----------------------------------------------------------------

    7. UserInfoVO.java (인증이 성공되면 사용자의 정보를 담아 두기 위한 Model)

    -----------------------------------------------------------------



    package login3;

    /**

    * 로그인이 정상적으로 이루어진 경우 사용자의 정보등을 저장 하는 빈

    * 본 예제에서는 ID와 PASSWORD를 저장 합니다.

    */

    public class UserInfoVO {

    private String id = null;

    private String pwd = null;



    //LoginDAO에서 인증이 성공인 경우 아래의 생성자를 불러 값을 setting 합니다.

    public UserInfoVO(String id, String pwd){

    this.id = id;

    this.pwd = pwd;

    }



    public String getId() {

    return id;

    }



    public String getPwd() {

    return pwd;

    }

    }





    -------------------------------------------------------

    8. Constants.java (LoginAction등에서 사용 될 상수를 정의)

    -------------------------------------------------------



    package login3;





    public class Constants {

    /**

    * 로그인한 사용자의 LoginForm이 저장될 세션 범위의 Attribute 이름

    */

    public static final String USER_KEY = "user";



    /**

    * ActionForward에서 사용되는 값

    */

    public static final String SUCCESS = "success";



    /**

    * ActionForward 로그인 동작을 나타내는 Tocken

    */

    public static final String LOGIN = "login";



    /**

    * ActionForward welcome 동작을 나타내는 Tocken

    */

    public static final String WELCOME = "welcome";





    }





    ---------------------------------------------------

    9. LogoffAction.java (로그오프 처리를 위한 ActionBean)

    ---------------------------------------------------



    package login3;



    import org.apache.struts.action.Action;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpSession;

    import javax.servlet.http.HttpServletResponse;



    import login3.LoginForm;



    import org.apache.struts.action.ActionForm;

    import org.apache.struts.action.ActionForward;

    import org.apache.struts.action.ActionMapping;



    public class LogoffAction extends Action {



    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {



    //필요한 어트리뷰트를 뽑아 냅니다.

    //LoginAction에서 사용자의 로그온개체를 Consants.USER_KEY라는 이름으로 세션에 저장

    HttpSession session = request.getSession();

    UserInfoVO userinfo = (UserInfoVO)session.getAttribute(Constants.USER_KEY);



    if (userinfo != null) {

    //로그를 남기자

    StringBuffer buf = new StringBuffer("User Logout : " + userinfo.getId());

    servlet.log(buf.toString());

    }



    //사용자의 로그인을 삭제, session.invaidate() 의 경우 션의 모든 것을 무효화 시킴.

    session.removeAttribute(Constants.USER_KEY);



    //성공적으로 처리 되었음을 알림

    return (mapping.findForward(Constants.SUCCESS));



    }





    }



    --------------------------------------------------------------------

    10. IsLogin.java (커스텀 태그를 처리 하기 위한 핸들러, main.jsp에서 인증이 되었는지 안되었는지 검사하는 기능을 수행하며 인증이 안된 경우라면 login.jsp로 보냄)

    --------------------------------------------------------------------



    package login3;





    import javax.servlet.http.HttpSession;

    import javax.servlet.jsp.JspException;

    import javax.servlet.jsp.tagext.TagSupport;



    import login2.Constants;





    public final class IsLogin extends TagSupport {

    private String name = Constants.USER_KEY;

    private String page = "/login.jsp";



    public String getName() {



    return (this.name);



    }



    public void setName(String name) {



    this.name = name;



    }



    public String getPage() {

    return (this.page);

    }



    public void setPage(String page) {

    this.page = page;

    }



    public int doStartTag() throws JspException {



    return (SKIP_BODY);



    }



    public int doEndTag() throws JspException {



    // Is there a valid user logged on?

    boolean valid = false;

    HttpSession session = pageContext.getSession();

    if ((session != null) && (session.getAttribute(name) != null))

    valid = true;



    // Forward control based on the results

    if (valid)

    return (EVAL_PAGE);

    else {

    try {

    pageContext.forward(page);

    } catch (Exception e) {

    throw new JspException(e.toString());

    }

    return (SKIP_PAGE);

    }



    }



    /**

    * Release any acquired resources.

    */

    public void release() {



    super.release();

    this.name = Constants.USER_KEY;

    this.page = "/login.jsp";



    }

    }





    ------------------------------------------------------------------

    11. app.tld (/WEB-INF/에 위치) 앞의 커스템 태그 핸들러 및 커스텀 태그를 사용 하기 위한 tld 파일

    ------------------------------------------------------------------






    "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">





    1.0

    1.1

    Application Tag Library

    http://jakarta.apache.org/taglibs/struts-example-1.0



    Example Application.






    IsLogin



    login3.IsLogin



    empty







    Validate that there is a currently logged on user, by checking for



    the existence of a session-scope bean under the specified name.



    If there is no such bean, forward control to the specified page,



    which will typically be a logon form.



    name - Name of the session-scope bean to check for [user]

    page - Context-relative path to the logon page [/logon.jsp]










    name



    false



    true










    page



    false



    true












    ---------------------------

    12. struts-config.xml

    ---------------------------

















































    path="/LoginSubmit"

    type="login3.LoginAction"

    name="loginForm"

    validate="true"

    input="/login.jsp"

    />






    path="/logoff"

    type="login3.LogoffAction"

    validate="false"

    />




    댓글 없음:

    댓글 쓰기