본문 바로가기

개발(합니다)/Java&Spring

Spring Security 정리(2) : DB 연결

반응형

Spring Security 정리(1) : 로그인 화면 포스팅을 일부는 이어서 작성하지 않고 새롭게 작성했습니다.



login 폴더 구성

1. security-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
    xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <http pattern="/resources/**/*.js" security="none" />
    <http pattern="/resources/**/*.css" security="none" />


   <beans:bean id="customizeAuthenticationSuccessHandler"
        class="com.otrodevym.mfaw.common.security.custom.CustomizeAuthenticationSuccessHandler" />
    <beans:bean id="customizeAuthenticationFailureHandler"
        class="com.otrodevym.mfaw.common.security.custom.CustomizeAuthenticationFailureHandler" />
    <beans:bean id="bcEncoder"
        class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />



    <http use-expressions="true" auto-config="true"
        disable-url-rewriting="true">
        <intercept-url pattern="/**" access="permitAll" />
        <intercept-url pattern="/user/**"
            access="hasAnyRole('USER,ADMIN')" />
        <intercept-url pattern="/admin/**"
            access="hasRole('ADMIN')" />

        <form-login login-page="/login"
            username-parameter="user_id" password-parameter="user_passwd"
            default-target-url="/"
            login-processing-url="/j_spring_security_check"
            authentication-success-handler-ref="customizeAuthenticationSuccessHandler"
            authentication-failure-handler-ref="customizeAuthenticationFailureHandler" />

        <access-denied-handler
            error-page="/login/not_authority" />
        <session-management invalid-session-url="/">
            <concurrency-control max-sessions="1"
                expired-url="/" />
        </session-management>
        <csrf disabled="true" />
        <remember-me remember-me-parameter="remember-me"
            remember-me-cookie="remember-me" />
        <logout invalidate-session="true"
            logout-url="/j_spring_security_logout" logout-success-url="/"
            delete-cookies="JSESSIONID,SPRING_SECURITY_REMEMBER_ME_COOKIE" />
    </http>

    <authentication-manager>
        <authentication-provider
            user-service-ref="customDataSource">
            <password-encoder ref="bcEncoder" />
        </authentication-provider>
    </authentication-manager>
    
    <beans:bean id="customDataSource"
        class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
        <beans:property name="dataSource" ref="dataSource" />
        <beans:property name="usersByUsernameQuery">
            <beans:value>
                SELECT user_id, password, enabled FROM login_info WHERE
                user_id=?
            </beans:value>
        </beans:property>
        <beans:property name="authoritiesByUsernameQuery">
            <beans:value>
                SELECT user_id, password, CASE WHEN authority = '1' THEN
                'ROLE_USER' when
                authority = '2' then 'ROLE_ADMIN' END AS ROLE_ID
                FROM
                login_info WHERE
                user_id=?
            </beans:value>
        </beans:property>
    </beans:bean>


</beans:beans>



<beans:property name="userByUsernameQuery">의 value는 유저가 있는지 확인합니다.


<beans:property name="authoritiesByUsernameQuery">의 value는 권한을 설명합니다.

 


authentication-success-handler-ref

authentication-failure-handler-ref

두개를 설정해 주지 않으면 POST /login로 날라가는데 이유를 모르겠다.

위에 두개를 추가하지 않으면 /login이 디폴트인데 알아서 처리해주겠끔 하려고 했는데 컨트롤러를 만들고 받아서 커스텀으로 처리해줘야한다.

그래서 컨트롤러를 만드는것보다 핸들러 두개를 추가해서 처리 해주었다.

 

2. CustomizeAuthenticationFailureHandler

import java.io.IOException;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;


public class CustomizeAuthenticationFailureHandler implements AuthenticationFailureHandler {
    
    @Autowired
    private BCryptPasswordEncoder new_encoder;
    

    @Override
    public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse res,
            org.springframework.security.core.AuthenticationException exception)
throws IOException, ServletException {
        new_encoder = new BCryptPasswordEncoder();
        System.err.println("로그인 실패");

//      System.err.println("user_passwd : " + encoder.encode(req.getParameter("user_passwd")));
        
        
        res.sendRedirect(req.getContextPath() + "/login?error=true");
        
//      req.getRequestDispatcher("/login.do").forward(req, res);        
    }
}

로그인 실패시 처리 내용을 작성합니다.


3. CustomizeAuthenticationSuccessHandler

import java.io.IOException;

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

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

public class CustomizeAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(
HttpServletRequest req, HttpServletResponse res, Authentication auth)
            throws IOException, ServletException {
        System.err.println("로그인 성공");
        res.sendRedirect(req.getContextPath() + "/");
    }

}

로그인 성공시 처리 내용을 작성합니다.


4. DB 생성

CREATE TABLE public.login_info
(
  user_id character varying NOT NULL, -- 유저 아이디
  password character varying, -- 비밀번호
  authority character varying DEFAULT 1, -- 권한
  enabled character varying DEFAULT 1 -- 사용 여부
)



5. JDBC : remix 등록

    <bean id="dataSourceSpied"
    class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName"
        value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>
    <bean id="dataSource"
        class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
        <constructor-arg ref="dataSourceSpied" />
        <property name="logFormatter">
            <bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter">
                <property name="loggingType" value="MULTI_LINE" />
                <property name="sqlPrefix" value="SQL : " />
            </bean>
        </property>
    </bean>


DB를 연결하고 jdbc.properties도 생성 후 작성합니다.



실패시


성공시




반응형