본문 바로가기

플밍 is 뭔들/SPRING

[SPRING SECURITY] 4.스프링 시큐리티 로그인 커스터마이징

1) 커스터 마이징을 위한 .java, .jsp

CustomAuthenticationProvider.java (DB에서 사용자 불러와 권한조회 하기)
 - <authentication-manager>에 추가한 클래스로써 권한확인 작업을 한 후 return result;를 하면 result의 내용이 
    <form-login> 에서 default-target-url에 선언한 컨트롤러로 넘어간다
public class CustomAuthenticationProvider implements AuthenticationProvider {
      @Autowired
      CustomService customService;
      
      @Override
      public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            
        String user_id = (String)authentication.getPrincipal(); //아이디 받기
        String user_pw = (String)authentication.getCredentials(); //비밀번호 받기
            
        CustomUserDetail customUserDetail = new CustomUserDetail(); //
         
          /*
          *     DB작업 및 로그인과 관련된 처리를 한다.
          *     만약 <form-login>의 default=target-url 속성에 보내고싶은 값이 있을 때는
          *     CustomUserDetail에 세팅을하고 아래에서 CustomUserDetail의 객체를 set해준다.
          */       

 
        //권한 설정하기 해당 사항에 맞는 권한을 선택하여 이용한다.
       
      if(권한있는 사용자가 아니다){ 
        List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
        roles.add(new SimpleGrantedAuthority("IS_AUTHENTICATED_ANONYMOUSLY"));

        } else if(권한있는 사용자다 ){
        List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
        roles.add(new SimpleGrantedAuthority("ROLE_USER"));

        }
          
        //아이디, 비밀번호, 권한, customUserDetail 값 세팅
        UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(user_id, user_pw, roles);
        result.setDetails(customUserDetail);
            
        return result;
      }
      @Override
      public boolean supports(Class<?> authentication) {
            return authentication.equals(UsernamePasswordAuthenticationToken.class);
      }
}

CustomUserDetail.java 
public class CustomUserDetail implements UserDetails {
      
      private String user_id;
      private String user_pw;
      private String auth;
      private String name;
      
      public String getUser_id() {
            return user_id;
      }
      public void setUser_id(String user_id) {
            this.user_id = user_id;
      }
      public String getUser_pw() {
            return user_pw;
      }
      public void setUser_pw(String user_pw) {
            this.user_pw = user_pw;
      }
      public String getAuth() {
            return auth;
      }
      public void setAuth(String auth) {
            this.auth = auth;
      }
      public String getName() {
            return name;
      }
      public void setName(String name) {
            this.name = name;
      }
     
      @Override
      public Collection<? extends GrantedAuthority> getAuthorities() {
            // TODO Auto-generated method stub
            
            List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();   
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            return authorities;
      }
      
      @Override
      public String getPassword() {
            // TODO Auto-generated method stub
            return null;
      }
      @Override
      public String getUsername() {
            // TODO Auto-generated method stub
            return null;
      }
      @Override
      public boolean isAccountNonExpired() {
            // TODO Auto-generated method stub
            return true;
      }
      @Override
      public boolean isAccountNonLocked() {
            // TODO Auto-generated method stub
            return true;
      }
      @Override
      public boolean isCredentialsNonExpired() {
            // TODO Auto-generated method stub
            return true;
      }
      @Override
      public boolean isEnabled() {
            // TODO Auto-generated method stub
            return true;
      }
}

Controller.java
      @RequestMapping(value="/loginInvalidCheck")
      public String loginInvalidId(Model model, HttpSession session, HttpServletRequest request){
            
            //customUserDetail에 set한 값을 getter를 통해 가져오는 작업을 가능하게 함
            CustomUserDetail userDetails = (CustomUserDetail)SecurityContextHolder.getContext().getAuthentication().getDetails();
            
            //이런식으로 세션에 값을 넣어주면 컨트롤러에서 사용가능
            session.setAttribute("id", userDetails.getUser_id());
            session.setAttribute("auth", userDetails.getAuth());
            session.setAttribute("loginDate", userDetails.getLoginDate());
            
            return "goIndex";
      }
      
      @RequestMapping(value="/login")
      public String login(Model model, HttpServletRequest request){
            return "login";
      }
      
      @RequestMapping(value="/login_duplicate")
      public String loginDuplicate(Model model, HttpServletRequest request){
            
            return "loginDuplicate";
      }

     @RequestMapping(value="/logout")
     public String pageLogin(HttpServletRequest request){
  
            session.invalidate();

            return "login";
      }
      
      @RequestMapping(value = "/")
      public String Index(Locale locale, Model model, HttpServletRequest request) throws ParseException {
            
                    //이런식으로 세션 사용 가능
            HttpSession session = request.getSession();

            String id = (String)session.getAttribute("id");
            String name =(String)session.getAttribute("name");
            String loginDate =(String)session.getAttribute("loginDate");

          /*
           *  웹페이지의 첫화면에 맞는 작업을 처리함.
           */

            return "index";
      }

goIndex.jsp
 - 브라우저 상의 url이 localhost:8080/loginInvalidCheck로 표시되었다.
   주소창의 url은 invalidCheck인데 화면은 웹페이지의 첫 화면이 뜨는게 보기 싫어서 추가 한 페이지이다.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="true" contentType="text/html; charset=utf-8" %>
<html>
<head>
<script src="<c:url value="/resources/js/jquery/jquery-1.9.1.min.js" />"></script>
<script type="text/javascript">
      
      $(document).ready(function(){
            location.href= "/";
      });
      
</script>
</head>
<body>
</body>
</html>

login_duplicate.jsp
 - 여기서 다음 url은 "/"로 되어있다. "/"는 Index 페이지로써 웹페이지의 첫 화면이다.
   중복로그인이 발생한 상태에서 이 브라우저의 사용자는 세션이 끊긴 상태이므로 "/" url을 호출해도 login 페이지로 넘어간다. 
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="true" contentType="text/html; charset=utf-8" %>
<html>
<head>
<script src="<c:url value="/resources/js/jquery/jquery-1.9.1.min.js" />"></script>
<script type="text/javascript">
      $(document).ready(function(){
            
            alert("[동시접속 발생] 다른 브라우저에서 해당 계정의 접속이 감지되어 로그아웃 됩니다.");
            location.href= "/";
      });
      
</script>
</head>
<body>
</body>
</html>