2011년 8월 10일 수요일

SSO(Single Sign On) : 통합 인증 로그인, 단일 사용 승인

# JOSS (Java Open Single Sign-On)

SSO란 Single Sign On 의 약자로 여러개의 사이트에서 한번의 로그인으로 여러가지 다른 사이트들을 자동적으로 접속, 사용하는 방법을 말한다.

일반적으로 서로 다른 시스템, 서로 다른 사이트에서는 각각의 사용자 정보를 관리하게 된다.

하지만 필요에 의해서 각각의 사용자 정보를 연동하여 사용해야 할 경우가 생긴다.

이때 하나의 사용자 정보를 기반으로 여러 시스템을 하나로 개발하기에는 많은 어려움이 따른다. 따라서 각각의 정보를 그대로 두고 통합인증을 사용하게 된다.

이때 각각의 시스템에 로그인할 때 통합 인증 정보가 있는지 확인하고 통합인증정보가 있을경우 타 시스템에서 자동으로 로그인 가능하도록 처리하고, 없을 때는 로그인하면서 통합인증정보를 생성하여 다른 시스템에서 참조 가능하도록 하는 것이다.


** SSO와 세션 클러스터링 의미비교

Single Sign On(통합인증)을 "하나의 아이디/패스워드로 여러 어플리케이션에 접근할 수 있도록 관리하는
통합시스템"을 의미하는 개념적인 층위의 용어라고 할 때, 자바에서의 세션 클러스터링은 이를 구체화한 실제 방법론중의 하나, 즉 SSO의 하위개념으로 해석할 수 있을 듯 합니다.

또한, 자바 세션 클러스터링은 일반적 SSO의 기능인 사용자의 로그인 여부 판별과 고유 아이디 인증을 넘어서, 단일 어플리케이션 상황에서와 마찬가지의 세션 스코프 유지를, 별개의 어플리케이션 또은 물리서버 사이에서도 가능하도록 하는 데에 초점이 맞춰져 있는 논제같습니다.
즉, 다수의 어플리케이션간에 세션 스코프를 연결하고, 스코프에 저장되는 자바 오브젝트들의 상태를 유지할 수 있도록 보장하는 것입니다.


** A,B,C,D 서버가 있다고 할 때의 일반적인 SSO 구현방식

** 1.
사용자가 로그인을 성공할 경우 로그인 처리 페이지가 A,B,C,D 서버에 있는 각각의 loginok.jsp 페이지를
IFRAME을 통해 동시에 호출합니다.
이때, A,B,C,D 서버의 loginok.jsp 페이지는 해당 브라우저 사용자에 대해 로그인 처리를 하고, Requset에 담겨온 loginid를 이용해서 세션에 사용자정보를 담습니다. 로그아웃도 마찬가지로 처리합니다.
4개의 세션이 별개로 생기는 셈이지만, 이는 모두 공통된 하나의 브라우저에 대응하므로, 브라우저가
종료되면 동시에 소멸됩니다.
세션간의 연동(객체 전달같은)은 불가능하지만, 하나의 브라우저에 대해서 각각의 어플리케이션이
동일한 인증상태를 유지하고 있고, 각각의 세션에 저장된 사용자 정보가 동일한 것이라는 무결성을
획득할 수 있습니다.

** 2.
쿠키를 이용하는 방법 (가장 대중적, 메인 도메인이 같을 때)
로그인하면, 고유의 키를 만들어 쿠키에 저장합니다. 각각의 사이트에서는 쿠키에 담긴 이 키값의 여부로, 로그인 여부를 판단하고 세션을 생성하며 키값에 따른 고유한 사용자 정보를 뽑아와 세션에 저장합니다.
로그아웃시에는 쿠키를 지워줍니다.

** 3.
하나의 서버에서 인증처리를 전담하는 방법
로그인과 세션을 관리하는 A서버의 a페이지를, 통합인증이 필요한 모든 페이지에서 프레임으로 포함하고,
처리에 필요한 사용자정보를 여기에 요청, 응답받습니다. a페이지는 XMLHttpRequest를 이용 페이지 갱신없이 A서버의 다른 프로그램을 호출하고 응답을 얻어옵니다.

- 시나리오
1. 메인프레임에서 로그인프레임에 로그인여부 질의 top.loginFrame.getIsLogin();
2. 로그인 프레임의 a페이지는 응답받을 메인프레임의 함수를 이벤트로 등록후 서버측에 요청을 보냅니다.
sendRequest("./isLogin.jsp","data","top.mainFrame.isLogin");
3. 요청받은 서버는 세션을 참조하여 로그인 여부 판단, XMLHttpRequest에 응답합니다.
4. 서버에서의 응답값을 매개변수로 top.mainFrame.isLogin(isLogin); 이 실행됩니다.

일반적인 방법은 아닙니다.

** 4.
세션 클러스터링을 이용한 방법
고유한 키값을 쿠키나 기타 장소에 보관하고, 별개의 서버 프로그램과 소켓으로 통신하여 키값에 대해 배당된 컬렉션에서, 직렬화된 자바객체를 꺼내오거나 혹은 저장하며 그 상태를 유지시키는 방법입니다. 키값(연결)이 유지되는 한, 저장소내의 동일한 객체에 접근할 수 있다는 보장을 만들어줍니다. 즉, 통합 인증보다는, 인증 후의 데이터 공유에 촛점이 맞춰져 있는 것 같습니다.

** 5.
통합인증 솔루션 사용


2011년 1월 10일 월요일

jQuery : 자동 Tab 이동

 

[code as3]

 /**
  * function :  Move Tab         카테고리 Tab 이동
  *
  * param   :  move_url         이동할 url 명(input 의 id, name 명)    
  *  
  */
   function moveTab(move_url){
   alert(move_url);
   eval('$("#form 이름").attr("action",  "/이동할 path/' + move_url + '.do").submit();');
 }

[/code]

jQuery : 날짜 new Date()

var date = new Date();

var Today = new Array();

 

Today['Year'] = date.getFullYear();

Today['Month'] = date.getMonth();

Today['Day'] = date.getDate();

2010년 12월 20일 월요일

jQuery : each() break / continue

 

 

for 문과 같은 기능 each()

 

$("#아이디명").each(function(i, obj){

      return false // break

      return true // continue

});

2010년 11월 24일 수요일

javascript getElementBy-----() 함수 : IE(InternetExplorer)와 FF(FireFox) 차이

1. getElementById() - document.getElementByid("값")

 

- id를 이용해서 특정 태그 객체를 찾음.

 

- id는 원래 html 문서내에서 유일해야 하므로 지정된 id를 가진 태그가 없거나,

 

  두개 이상이면 getElementByid 메서드는  null로 리턴.

 

ex) 

 

<script type="text/javascript">

    var a = document.getElementByid("test");

    alert(a.value);

</script>

 

<input id="test" value="one">

 

# IE : ID와 Name 둘다 찾아 먼저 나온 것 하나를 return.

  ( IE8부터 FF와 동일하게 ID만 찾음 )

# FF : ID만 찾아 먼저 나온 것 하나를 return.

 

 

2. getElementsByName() - document.getElementsByName("값")

 

- name 이 같은 객체를 배열로 가져오는 매소드.

 

- 지정된 이름이나 태그이름을 가진 태그 객체의 배열을 리턴하며,

 

  객체를 찾지 못하면 길이가 0인 배열을 리턴함.

 

- 중복되지 않게 이름을 고유하게 줬더라고 배열로 들어와서 0번을 차지함.

 

# getElementByName 이란 method는 존재하지 않음.

 

ex)

 

<script type="text/javascript">

    var a = document.getElementsByName("test");

    document.write("배열 값 출력 : ");

    for(var i=0; i<a.length; i++){

        document.write(a.value[i] + " ");

    }

</script>

 

<input type="text" name="NAME" />

<input type="hidden" name="test" value="one" />

<input type="hidden" name="test" value="two" />

<input type="hidden" name="test" value="three" />

 

3. getElementByTagName() - document.getElementsByTagName("태그명")

 

- 요소노드의 태그명을 가지고 접근하는 메소드.

 

ex)

<script type="text/javascript">

    function fun(){

        var items = document.getElementsByTagName("");

        alert(items.length);

        window.onload = func;

    }

</script>

 

 

 

- 문서내의 태그명들을 모두 불러와 items 이라는 변수에 저장하게 된다.  

 

- items 라는 변수는 물론 객체변수이고, 만약에 문서내 태그명들이 여러개라면

 

  items라는 변수는 1차원 배열이 된다. (items[0], items[1], items[2] ... )

 

- items.length : 문서내에 존재하는 태그의 갯수이다.

 

 

 

 

 

2010년 11월 15일 월요일

@RequestParam

@RequestParam

 

 

- RequestParam annotation은 key=value 형태로 화면에서 넘어오는 파라미터를 맵핑된

 

  메소드의 파라미터로 지정해준다.

 

- 주로 get 방식으로 들어오는 request에서 사용한다.

 

- 필수 요건이 아닐 경우, @RequestParam(value="id", required="false")와 같이 옵션을 주고

 

  사용할 수 있다.

 

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

 

@Controller
public class LoginController {

    @Autowired
    private LoginService loginService;

    @Autowired
    private SampleService sampleService;


    /**
     * 사용자로 부터 아이디, 패스워드를 입력받아 인증 성공이면 세션 객체에 계정정보를 담고 사원정보리스트 페이지로 포워딩한다. 인증에
     * 실패하면 로그인 페이지로 다시 리턴한다.
     */
    @RequestMapping("/loginProcess.do")
    public String login(HttpServletRequest request, @RequestParam("id") String id,
            @RequestParam("password") String password) {

        // TODO [Step 4-1-01]
        // LoginService의 authenticate메소드를 이용하여 로긴여부 체크 Account 객체를 리턴 받는다.
     Account account = (Account) loginService.authenticate(id, password);

       
        /*
         * TODO [Step 4-1-03]
         * 가져온 account 객체가 null 아닌 경우
         * request.getSession() 메소드를 통해 Session을 구해 UserAccount 이름으로 Session 에
         * Attribute로 저장한다. 그리고 "redirect:/loginSuccess.do" 값을 반환한다. null 인경우
         * "login" 반환한다.
         */
     if (account != null) {
      request.getSession().setAttribute("UserAccount", account);
      return "redirect:/loginSuccess.do";
      } else {
      return "login";
      }
    }

    // TODO [Step 4-1-04]
    // loginSuccess.do 로 호출된 처리(@RequestMapping(value="/loginSuccess.do", method=RequestMethod.GET) 를 위한
    // 메소드(loginSuccess) 를 void 타입의 public 메소드를 만들어라.
    @RequestMapping(value = "/loginSuccess.do", method = RequestMethod.GET)
    public void loginSuccess() {
    }

    @RequestMapping("/exception.do")
    public String invokeException(@RequestParam("id") String id ) throws Exception {
       
        sampleService.invokeMethodAException();
       
        return null;
    }

@Controller

@Controller

 

- Controller annotation으로 Controller interface 및 class의 기능을 간단하게 사용할 수 있다.

 

- Annotation을 사용하지 않고, Controller를 직접 상속받아 쓰는 경우 필요한 xml 설정을

 

  생략할 수 있다.

 

- SimpleFormController, MultiActionController 등 Controller의 종류를 명시하지 않고

 

  @Controller 설정만으로 사용할 수 있다.

 

- xxx-servlet.xml 파일에서 component-scan 으로 web controller가 있는 패키지를 명시해

 

  줌으로써, 별도의 bean 설정을 하지 않아도 @Controller로 등록된 클래스 파일에 대한

 

  bean을 자동으로 생성해준다.

 

- Controller로 사용하고자 하는 클래스에 @Controller 지정해주면 component-scan으로

 

  자동 등록된다.

 

 

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

 

@Controller
public class LoginController {

    @Autowired
    private LoginService loginService;

    @Autowired
    private SampleService sampleService;


    /**
     * 사용자로 부터 아이디, 패스워드를 입력받아 인증 성공이면 세션 객체에 계정정보를 담고 사원정보리스트 페이지로 포워딩한다. 인증에
     * 실패하면 로그인 페이지로 다시 리턴한다.
     */
    @RequestMapping("/loginProcess.do")
    public String login(HttpServletRequest request, @RequestParam("id") String id,
            @RequestParam("password") String password) {

        // TODO [Step 4-1-01]
        // LoginService의 authenticate메소드를 이용하여 로긴여부 체크 Account 객체를 리턴 받는다.
     Account account = (Account) loginService.authenticate(id, password);

       
        /*
         * TODO [Step 4-1-03]
         * 가져온 account 객체가 null 아닌 경우
         * request.getSession() 메소드를 통해 Session을 구해 UserAccount 이름으로 Session 에
         * Attribute로 저장한다. 그리고 "redirect:/loginSuccess.do" 값을 반환한다. null 인경우
         * "login" 반환한다.
         */
     if (account != null) {
      request.getSession().setAttribute("UserAccount", account);
      return "redirect:/loginSuccess.do";
      } else {
      return "login";
      }
    }

    // TODO [Step 4-1-04]
    // loginSuccess.do 로 호출된 처리(@RequestMapping(value="/loginSuccess.do", method=RequestMethod.GET) 를 위한
    // 메소드(loginSuccess) 를 void 타입의 public 메소드를 만들어라.
    @RequestMapping(value = "/loginSuccess.do", method = RequestMethod.GET)
    public void loginSuccess() {
    }

    @RequestMapping("/exception.do")
    public String invokeException(@RequestParam("id") String id ) throws Exception {
       
        sampleService.invokeMethodAException();
       
        return null;
    }
   
}