본문 바로가기
spring

spring framewrok MVC - 6 ( 부제 : spring security 적용해보기 )

by devante 2014. 10. 29.




pom.xml 하기 dependency 추가...

 <properties>
    <java-version>1.6</java-version>
    <org.springframework-version>3.1.1.RELEASE</org.springframework-version>
    <org.aspectj-version>1.6.10</org.aspectj-version>
    <org.slf4j-version>1.6.6</org.slf4j-version>
</properties>


<!-- spring security -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>${org.springframework-version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>${org.springframework-version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>${org.springframework-version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>${org.springframework-version}</version>
</dependency>




spring/security-context.xml 생성... 일단 생성 -_-



web.xml – filter 추가

<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/*-context.xml</param-value>

     *** 일단은 기존 root-context 에서 security-context.xml 을 추가했기때문에 위와 같이 변경;;
</context-param>


<!-- spring security  -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping> 



Configuration 상세 – 생성한 spring/sercurity-context.xml 정리;;

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
   
    <security:http pattern="/resources/**" security="none"/>
       
    <security:http auto-config="true">
        <security:intercept-url pattern="/views-people/" access="ROLE_USER,ROLE_ADMIN" />

        *** 이후부터 /views-people 폴더내의 파일들에 대한 접근은 위의 두 권한으로 제한한다
        <security:form-login login-page="/signin.do"
            authentication-success-handler-ref="loginSuccessHandler"
            authentication-failure-handler-ref="loginFailureHandler" />

         *** 로그인 페이지 커스텀 처리, 만약 설정하지않는다면 스프링 자체적으로 지원하는 로그인 페이지로

            이동하게 된다. 로그인 각각의 성공 / 실패시 핸들러 처리 추가;

        <security:logout logout-success-url="/" /> 
    </security:http>
   
    <bean id="loginSuccessHandler" class="com.spring.handler.LoginSuccessHandler"></bean>
    <bean id="loginFailureHandler" class="com.spring.handler.LoginFailureHandler"></bean>
   
    <bean id="PredeUserService" class="com.spring.service.PredeUserService">
        <constructor-arg name="sqlSession" ref="sqlSession" />
    </bean>
       
    <security:authentication-manager>
        <security:authentication-provider user-service-ref="PredeUserService" />
    </security:authentication-manager>

</beans> 


class 처리 - PredeUserService.java

package com.spring.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

//import com.spring.service.PredeUser;

public class PredeUserService implements UserDetailsService {
   
    private static final Logger logger = LoggerFactory.getLogger(PredeUserService.class);
    private SqlSessionTemplate sqlSession;
   
    public PredeUserService() {
        // TODO Auto-generated constructor stub
    }
       
    public PredeUserService(SqlSessionTemplate sqlSession) {
        // TODO Auto-generated constructor stub
        this.sqlSession = sqlSession;
    }

    @Override
    public UserDetails loadUserByUsername(String username)

            throws UsernameNotFoundException {

        *** UserDetailsService 를 implement 했다면 기본 셋팅되는 메소드..  

         실제 org.springframework.security.core.userdetails.UserDetailsService 이 jar 를 열어보면 이 메소드밖에 없다
        // TODO Auto-generated method stub
       
        Map<String, Object> prede = sqlSession.selectOne("userControlMapper.searchByUsername", username);
        *** mapper.xml 을 통해 선언한 sql select 문

    <select id ="searchByUsername" parameterType="String" resultType= "java.util.HashMap">
        select
            username as username,
            password as password,
            authority as authority
        from pred where username=#{username}
    </select >



        if(prede == null ) throw new UsernameNotFoundException(username);
       
        logger.info(prede.toString());
       
        List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
        roles.add(new SimpleGrantedAuthority(prede.get("authority").toString()));

        *** db table 에 authority 칼럼을 만들어놓은 상태, default 는 ROLE_USER 로;;;

        UserDetails user = new User(prede.get("username").toString(), prede.get("password").toString(), roles);   
        return user;
    }
   
}  



class 처리 - LoginSuccessHandler.java

package com.spring.handler;

import java.io.IOException;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.web.bind.annotation.SessionAttributes;

@SessionAttributes("username")
public class LoginSuccessHandler implements AuthenticationSuccessHandler {

    private static final Logger logger = LoggerFactory.getLogger(LoginSuccessHandler.class);
   
    @Override
    public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse res, Authentication auth) throws IOException, ServletException {

        // TODO Auto-generated method stub
        logger.info(auth.getName());
        logger.info(auth.getAuthorities().toString());
        logger.info(auth.getDetails().toString());
        logger.info(auth.getPrincipal().toString());
       
        for(GrantedAuthority a : auth.getAuthorities()){
            logger.info(a.getAuthority());
        }
   
        UserDetails u = (UserDetails) auth.getPrincipal();
   
        logger.info(String.valueOf(u.isAccountNonExpired()));
        logger.info(String.valueOf(u.isAccountNonLocked()));
        logger.info(String.valueOf(u.isCredentialsNonExpired()));
        logger.info(String.valueOf(u.isEnabled()));
       
        System.out.println("LoginSuccessHandler LoginSuccessHandler" + u.getUsername());
        //session.setAttribute("username", u.getUsername());
   
        res.sendRedirect(req.getContextPath() + "/answer.do");

    }

    //public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth) throws IOException, ServletException
    //{
    //    response.sendRedirect(request.getContextPath() + "/answer.do");
    //}
}


class 처리 - LoginFailureHandler.java

package com.spring.handler;

import java.io.IOException;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

public class LoginFailureHandler implements AuthenticationFailureHandler {
   
    private static final Logger logger = LoggerFactory.getLogger(LoginFailureHandler.class);

     @Override
     public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse res, AuthenticationException auth) throws IOException, ServletException {

         // TODO Auto-generated method stub
         logger.info(auth.getLocalizedMessage());
         logger.info(auth.getMessage());
   
         for(StackTraceElement s : auth.getStackTrace()){
             logger.info(s.getClassName());
             logger.info(s.getFileName());
             logger.info(s.getMethodName());
             logger.info(s.getLineNumber()+"");
             logger.info(s.isNativeMethod()+"");
         }
   
         req.setAttribute("errMsg",auth.getMessage());
         req.getRequestDispatcher("/signin.do").forward(req, res);

     }

    //public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException auth) throws IOException, ServletException
    //{
    //    response.sendRedirect(request.getContextPath() + "/");
    //}
}


jsp 파일 -_- signin.jsp

.

.

<form method="post" class="signin" action="j_spring_security_check">

*** sigin 부분에서 해당 action 을 j_spring_security_check 로 변경

.

.


security 에서의 session 처리에 대한 해당 값 받아오기

jsp 파일 -_- answer.jsp

<%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<%@ page import="java.util.*" %>
<%@ page import="org.springframework.security.core.context.SecurityContextHolder" %>
<%@ page import="org.springframework.security.core.userdetails.User" %>

<%@ taglib prefix="s" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page session="true" %>
<%
    User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();

   String username = user.getUsername();

%>

.

.

.

<div style="width:800; height:400" align=center>
    <br/><br/>
    <h1>
    SecurityContextHolder...username : <%= username%><br/>
    </h1><br/>



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


음.. 뭐 별개로... spring security 상에서의 세션(?;) 으로 값을 받아올수도 있겠지만..

간단하게 -_-

컨트롤러에서 그냥 세션으로 집어넣어봤다;;

package com.spring.prede;

import javax.servlet.http.HttpSession;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;

@Controller
@SessionAttributes("username")
public class LoginController {
    
    @RequestMapping("/answer.do")
    public String answer(HttpSession session, Model model) {          
        
        User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String se_username = user.getUsername();
        
        session.setAttribute("username", se_username);
              
        return "answer";
    }  
}


테스트야 뭐 간단하다 -_- answer.jsp 에서 세션스콥으로 받아와봄 -_-

<div style="width:800; height:400" align=center>
    <br/><br/>
    <h1>
    SecurityContextHolder...username : <%= sec_username%><br/>
    Session.................username : ${ sessionScope.username }<br/> 



반응형

댓글