테이블 생성

-> 저번장에 생성한 member 테이블은 삭제처리 

-> TB_AUTHORITES, TB_CODE, TB_GRP_CODE, TB_USERS 테이블을 생성

 

TB_AUTHORITIES 생성문 (권한테이블)
CREATE TABLE `tb_authorities` (
  `AUTH_IDX` int NOT NULL AUTO_INCREMENT COMMENT '인덱스',
  `USER_ID` varchar(45) DEFAULT NULL COMMENT '사용자 아이디',
  `AUTHORITY` varchar(45) DEFAULT NULL COMMENT '권한',
  PRIMARY KEY (`AUTH_IDX`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='권한테이블'

 

TB_CODE 생성문 (코드 테이블)
CREATE TABLE `tb_code` (
  `CODE_IDX` int NOT NULL AUTO_INCREMENT COMMENT '인덱스',
  `CODE_NO` varchar(45) NOT NULL COMMENT '코드번호',
  `CODE_NAME` varchar(45) DEFAULT NULL,
  `CODE_EXP` varchar(45) DEFAULT NULL COMMENT '코드명',
  PRIMARY KEY (`CODE_IDX`,`CODE_NO`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='코드 테이블'

 

TB_GRP_CODE 생성문 (코드 그룹 테이블)
CREATE TABLE `tb_grp_code` (
  `GRP_CODE_IDX` int NOT NULL AUTO_INCREMENT COMMENT '인덱스',
  `GRP_CD_NO` varchar(20) DEFAULT NULL COMMENT '그룹코드 번호',
  `GRP_CD_EXP` varchar(45) DEFAULT NULL COMMENT '그룹 코드명',
  PRIMARY KEY (`GRP_CODE_IDX`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='코드 그룹 테이블'

 

TB_USERS 테이블 생성문 (사용자 테이블)
CREATE TABLE `tb_users` (
  `USER_IDX` int NOT NULL AUTO_INCREMENT COMMENT '인덱스',
  `USER_ID` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '사용자 아이디',
  `PASSWORD` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '패스워드',
  `USER_NAME` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '사용자 이름',
  `EMAIL` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '이메일',
  `HAND_PHONE_NO` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '핸드폰번호',
  `USE_YN` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '사용여부',
  PRIMARY KEY (`USER_IDX`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3

 

TB_GRP_CODE 데이터

-> 권한이라는 그룹 데이터를 생성

 

TB_CODE 데이터

-> 권한이라는 그룹 데이터 안에 관리자, 사용자가 있다고 생각하면됨

 

롬복 설정
intelij에서는 lombok을 gradle에 추가를 했을때는 바로 적용이 됬었는데 sts에서는 적용이 안되는 경우가 있어서
jar를 직접 실행해서 sts 경로를 설정하였음

https://projectlombok.org/download

 

Download

 

projectlombok.org

-> 해당 사이트에서 롬복 다운로드

-> 이후 해당 경로에 가서 java -jar lombok.jar 실행

 

 

 

 

-> Specify location 클릭후 이클립스 설치되어있는 경로를 선택후 install / update 클릭

-> 이후 이클립스 껏다가 다시키면 적용이 됨

 

admin 프로젝트 build.gradle 수정

 

build.gradle
apply plugin: 'war'
def timestamp = new Date().format('yyMMddHHmm')
bootWar.enabled = false // (1)
war.enabled = true  // (2)
war {
   archiveName = "admin-${version}-"+timestamp+".war"
}

dependencies {
	implementation project(':core')

	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	testImplementation('org.springframework.security:spring-security-test')
	
	//db
	runtimeOnly 'mysql:mysql-connector-java'
   
	// MyBatis
	implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2")
   
	testImplementation('org.springframework.boot:spring-boot-starter-test')
    
	// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools
	implementation group: 'org.springframework.boot', name: 'spring-boot-devtools', version: '2.2.6.RELEASE'

	providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
	
	implementation group: 'org.springframework.security', name: 'spring-security-core', version: '5.3.0.RELEASE'
	implementation group: 'org.springframework.security', name: 'spring-security-taglibs', version: '5.3.0.RELEASE'
   
	// Apache Http Requests
	implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.12'         // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
	
	// Tiles Setting
	implementation group: 'org.apache.tiles', name: 'tiles-jsp', version: '3.0.8'      // https://mvnrepository.com/artifact/org.apache.tiles/tiles-jsp
	implementation group: 'org.apache.tiles', name: 'tiles-core', version: '3.0.8'      // https://mvnrepository.com/artifact/org.apache.tiles/tiles-core
   
	/* Jsp Setting */
	implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: '9.0.31'   // https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper
	implementation group: 'org.apache.taglibs', name: 'taglibs-standard-impl', version: '1.2.5'      // https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-impl
	providedRuntime group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1'      // https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api
	implementation group: 'javax.servlet', name: 'jstl'                                    // https://mvnrepository.com/artifact/javax.servlet/jstl
	
	/* gson */
	implementation 'com.google.code.gson:gson:2.8.6'
}

-> security 추가하기, gradle 수정하면 refresh gradle 꼭 해줘야함!

 

core 프로젝트에 build.gradle 수정

 

build.gradle
bootJar{
    enabled = false;
}
jar {
    enabled = true;
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	
	//security core
	implementation group: 'org.springframework.security', name: 'spring-security-core', version: '5.3.1.RELEASE'
}

 

core 프로젝트안에 entity 패키지 생성후 그안에 UserAuthority.java, UserInfo.java 생성

UserAuthority.java
package com.board.entity;

import org.springframework.security.core.GrantedAuthority;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class UserAuthority implements GrantedAuthority {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private String authority;
	private String authorityNm;

	@Override
	public String getAuthority() {
		// TODO Auto-generated method stub
		return this.authority;
	}
}

-> 사용자 권한 관련 vo

 

UserInfo.java
package com.board.entity;

import java.util.Collection;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class UserInfo implements UserDetails {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	//사용자 id
	private String userId;
	
	//사용자 이름
	private String userName;
	
	//패스워드
	private String password;
	
	//이메일
	private String email;
	
	//핸드폰 반호
	private String handPhoneNo;
	
	//사용여부
	private String useYn;

	//권한 list
	public List<UserAuthority> authorities;
	
	//권한
	public String authority;
	
	//권한 이름
	public String authorityNm;
	
	public String auth;
	
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return authorities;
	}

	@Override
	public String getPassword() {
		return password;
	}

	@Override
	public String getUsername() {
		return userName;
	}

	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	public boolean isEnabled() {
		return true;
	}
}

-> 사용자 관련 vo

 

core 프로젝트 안에 dao 패키지 안에 UserMapper.java 생성

 

UserMapper.java
package com.board.dao;

import com.board.entity.UserInfo;
import com.board.entity.UserAuthority;

public interface UserMapper {

	//사용자 정보 조회
	UserInfo getUserInfo(String userId);
	
	//사용자 권한 조회
	UserAuthority getUserAuthorities(String userId);
	
	//사용자 등록
	public int insertUser(UserInfo userinfo);
	
	//사용자 권한 등록
	public int insertUserAuth(UserInfo userinfo);
	
	//사용자 중복체크
	int duplicateUserCheck(String userId);
	
}

 

application.properties 수정

# Deploy profile ( prod, stage, dev, local )
spring.profiles.active=local

# encoding
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true

#View Configuration
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

# model 프로퍼티 camel case 설정
mybatis.configuration.map-underscore-to-camel-case=true

# xml파일 result type에 패키지명을 생략할 수 있도록 alias 설정
mybatis.type-aliases-package=com.board.entity

-> xml에서 resultType를 읽을수 있도록 설정

 

resources 폴더안에 dao 패키지안에 UserMapper.xml 생성

 

UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- FAQ SQL Mapper -->
<mapper namespace="com.board.dao.UserMapper">

	<!-- 사용자 정보 조회 -->
	<select id="getUserInfo" parameterType="String" resultType="UserInfo">
		SELECT
             USER_ID
            ,USER_NAME
            ,PASSWORD
            ,EMAIL
            ,HAND_PHONE_NO
            ,USE_YN
        FROM
            TB_USERS
        WHERE
        	USER_ID = #{userId}    
    </select>
    
    <!-- 사용자 권한 조회 -->
	<select id="getUserAuthorities" parameterType="String" resultType="UserAuthority">
		SELECT
			TA.AUTHORITY
     		,(SELECT CODE_EXP FROM TB_CODE TCD WHERE TCD.CODE_NO = '200' AND TCD.CODE_NAME = TA.AUTHORITY) AS AUTHORITY_NM
		FROM
     		TB_AUTHORITIES TA
     	WHERE
     		TA.USER_ID = #{userId}	
     </select>

	<!-- 사용자 등록 -->
	<insert id="insertUser" parameterType="UserInfo">
		INSERT INTO
			TB_USERS(
				 USER_ID
				,PASSWORD
				,USER_NAME
				,EMAIL
				,HAND_PHONE_NO
				,USE_YN
			)
			VALUES(
				 #{userId}
				,#{password}
				,#{userName}
				,#{email}
				,#{handPhoneNo}
				,'1'
			)
	</insert>
	
	<!-- 사용자 중복체크 -->
	<select id="duplicateUserCheck" parameterType="String" resultType="int">
		SELECT
			COUNT(*)
		FROM
			TB_USERS
		WHERE
			USER_ID = #{userId}		
	</select>
	
	<!-- 사용자 권한 등록 -->
	<insert id="insertUserAuth" parameterType="UserInfo">
		INSERT INTO
			TB_AUTHORITIES(
				 USER_ID
				,AUTHORITY
			)
			VALUES(
				 #{userId}
				,'USER'
			)
	</insert>
	
</mapper>

 

core 프로젝트에 service패키지에 LoginService 생성

 

LoginService.java
package com.board.service;

import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.board.dao.UserMapper;
import com.board.entity.UserInfo;

@Service
public class LoginService {
	
	@Autowired
	UserMapper userMapper;
	
	@Autowired
	PasswordEncoder passwordEncoder;
	
	public Map<String, Object> checkLoginInsert(UserInfo userInfo) {
		
		Map<String, Object> result = new HashMap<String, Object>();
		
		//0이면 중복되는 아이디 없음
		int duplicateCheck = userMapper.duplicateUserCheck(userInfo.getUserId());
		
		//신규등록
		if(duplicateCheck == 0) {
			//패스워드 bcrypt 암호화
			String password = passwordEncoder.encode(userInfo.getPassword());
			userInfo.setPassword(password);
			
			//사용자 등록
			userMapper.insertUser(userInfo);
			result.put("resultCode", "00");
			result.put("resultMsg", "정상적으로 회원이 등록되었습니다.");
			
			//사용자 권한 등록
			userMapper.insertUserAuth(userInfo);
		}
		
		//중복된 아이디가 있으므로 에러
		else {
			result.put("resultCode", "99");
			result.put("resultMsg", "중복된 아이디가 있습니다. 아이디를 다시 입력해주세요.");
		}
		
	return result;
	}
	
}

 

admin 프로젝트에 exception 패키지 생성후 안에 파일 생성

UserIdException.java
package com.board.exception;

import org.springframework.security.core.AuthenticationException;

/**
 * The Class CUserNotFoundException.
 */
public class UserIdException extends AuthenticationException {
   
   /** The Constant serialVersionUID. */
   private static final long serialVersionUID = 1L;
    
    /**
     * Instantiates a new c user not found exception.
     *
     * @param msg the msg
     * @param t the t
     */
    public UserIdException(String msg, Throwable t) {
        super(msg, t);
    }

    /**
     * Instantiates a new c user not found exception.
     *
     * @param msg the msg
     */
    public UserIdException(String msg) {
        super(msg);
    }
}

 

UserAuthException.java
package com.board.exception;

import org.springframework.security.core.AuthenticationException;

/**
 * The Class CUserNotFoundException.
 */
public class UserAuthException extends AuthenticationException {
   
   /** The Constant serialVersionUID. */
   private static final long serialVersionUID = 1L;
    
    /**
     * Instantiates a new c user not found exception.
     *
     * @param msg the msg
     * @param t the t
     */
    public UserAuthException(String msg, Throwable t) {
        super(msg, t);
    }

    /**
     * Instantiates a new c user not found exception.
     *
     * @param msg the msg
     */
    public UserAuthException(String msg) {
        super(msg);
    }
}

 

admin 프로젝트 common 패키지에 CoTopComponent.java 생성

 

CoTopComponent.java
package com.board.common;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import com.google.gson.JsonObject;

/* 최상위 컴포넌트 */

public abstract class CoTopComponent {
	protected void writeResponse(HttpServletResponse res, JsonObject jsonObject) throws IOException{
		writeResponse(res, jsonObject.toString());
	}
	
	protected void writeResponse(HttpServletResponse res, String message) throws IOException{
		res.setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE);
		
		PrintWriter pw = res.getWriter();
		pw.write(message);
		pw.close();
	}
	
}

 

config 패키지안에 ClientAuthenticationProvider.java,  LoginSuccessHandler.java, LoginFailHandler.java, SpringSecuritySessionRegistImpl.java, SecurityConfig.java 생성

AdminAuthenticationProvider.java
package com.board.config;

import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import com.board.dao.UserMapper;
import com.board.entity.UserAuthority;
import com.board.entity.UserInfo;
import com.board.exception.UserAuthException;
import com.board.exception.UserIdException;
import org.springframework.security.crypto.password.PasswordEncoder;

/** 로그인 provider */
@Component
public class AdminAuthenticationProvider implements AuthenticationProvider{
	
	@Autowired 
	UserMapper userMapper;
	
	@Autowired
	PasswordEncoder passwordEncoder;
	
	@SuppressWarnings("unchecked")
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
	UsernamePasswordAuthenticationToken authToken = (UsernamePasswordAuthenticationToken) authentication;
		
		//아이디
		String id = (authToken.getName()).toUpperCase();
		
		//비밀번호
		String pwd = (String) authToken.getCredentials();
		
		//해당 사용자 정보 조회
		UserInfo userInfo = userMapper.getUserInfo(id);
		
		//해당 사용자가 있을경우
		if(userInfo != null ) {	
			//입력한 비밀번호가 현재 비밀번호와 같지 않으면
			if(!(passwordEncoder.matches(pwd, userInfo.getPassword()))) {
				throw new UserIdException("접속 할 수 없습니다. \n아이디 또는 비밀번호를 확인해주세요.");
			}
			
			//입력한 비밀번호가 현재 비밀번호와 같으면
			else {
				List<UserAuthority> authorities = new ArrayList<>();
				
				//권한 조회
				UserAuthority getUserAuthorities = userMapper.getUserAuthorities(authToken.getName());
				
				//권한이 있을경우
				if(getUserAuthorities != null) {
					UserAuthority auth = new UserAuthority();
					auth.setAuthority(getUserAuthorities.getAuthority());
					auth.setAuthorityNm(getUserAuthorities.getAuthorityNm());
					authorities.add(auth);
					userInfo.setAuthorities(authorities);					
				}
				
				//권한이 없을 경우
				else {
					throw new UserAuthException("접속권한이 없습니다. \n관리자에게 권한을 요청해주세요.");
				}
			}
		}
		
		//해당 사용자가 없을경우
		else {
			throw new UserIdException("접속 할 수 없습니다. \n아이디 또는 비밀번호를 확인해주세요.");
		}
		
		List<GrantedAuthority> authorities = (List<GrantedAuthority>) userInfo.getAuthorities();
		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userInfo, "1", authorities);
		
		return token;
	}



	@Override
	public boolean supports(Class<?> authentication) {
		return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
	}
	
}

 

LoginSuccessHandler.java
package com.board.config;

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.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import com.board.common.CoTopComponent;
import com.board.entity.UserInfo;
import com.google.gson.JsonObject;

/* 로그인 성공시 타는 handler */
@Component
public class LoginSuccessHandler extends CoTopComponent implements AuthenticationSuccessHandler {
	
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication auth) throws IOException, ServletException {
		
		//default 성공
		String resultCode = "00";
		
		HttpSession session = request.getSession(true);
		session.setMaxInactiveInterval(60 * 60 * 3);
		
		session.setAttribute("sessUserInfo",((UserInfo) auth.getPrincipal()));
	    session.setAttribute("authority",((UserInfo) auth.getPrincipal()).getAuthority());
	    session.setAttribute("authorityNm",((UserInfo) auth.getPrincipal()).getAuthorityNm());
	    session.setAttribute("auth",((UserInfo) auth.getPrincipal()).getAuth());
	    
	    //Response 결과 값을 넣어줌
	    JsonObject loginResult = new JsonObject();
	    loginResult.addProperty("resultCode", resultCode);
	    loginResult.addProperty("targetUrl", request.getContextPath()+"/");
	    
	    //응답 전송
	    writeResponse(response, loginResult);
	}
	
}

 

LoginFailureHandler.java
package com.board.config;

import java.io.IOException;

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

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import com.board.common.CoTopComponent;
import com.board.exception.UserAuthException;
import com.board.exception.UserIdException;
import com.google.gson.JsonObject;

import lombok.extern.slf4j.Slf4j;

/* 로그인 실패시 타는 핸들러 */

@Slf4j
@Component
public class LoginFailureHandler extends CoTopComponent implements AuthenticationFailureHandler {

	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {
		writeResponse(response, parseException(request.getParameter("un"), exception));
	}
	
	private JsonObject parseException(String userName, AuthenticationException exception) {
		String errCode = "99";
		String errMsg = exception.getMessage();

		//존재하지 않는 아이디
		if( exception instanceof UserIdException) {
			log.error("존재하지않는 아이디입니다.");
		}
		
		//권한이 없을경우
		else if( exception instanceof UserAuthException) {
			log.error("권한이 없는 아이디입니다.");
		}
		
		JsonObject result = new JsonObject();
		result.addProperty("resultCode", errCode);
		result.addProperty("resultMessage", errMsg);
		return result;
	}
}

 

SpringSecuritySessionRegistImpl.java
package com.board.config;

import org.springframework.security.core.session.SessionRegistryImpl;

public class SpringSecuritySessionRegistImpl extends SessionRegistryImpl {
}

 

SecurityConfig.java
package com.board.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.board.common.Constants;
import com.board.common.Url;

/* 시큐리티 설정 */
@Configuration
@EnableWebSecurity
@ComponentScan(value = Constants.APP_DEFAULT_PACKAGE_NAME)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private LoginSuccessHandler loginSucessHandler;
	
	@Autowired
	private LoginFailureHandler loginFailureHandler;
	
	/* configure */
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationProvider(new AdminAuthenticationProvider());
		super.configure(auth);
	}
	
	/* http 요청 검사 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		
		http
			.csrf().disable()
			.authorizeRequests()
			.antMatchers("/auth/**").permitAll()					//로그인, 회원가입 접속허용
			.antMatchers("/resource/**/images/**").permitAll()		//이미지
			.anyRequest().authenticated()
		.and()
		
		//로그인 화면 설정
		.formLogin()
			.permitAll()
			.loginPage(Url.AUTH.LOGIN)
			.loginProcessingUrl(Url.AUTH.LOGIN_PROC)
			.successHandler(loginSucessHandler)
			.failureHandler(loginFailureHandler)
			.usernameParameter(USERNAME_PARAM)
			.passwordParameter(PASSWORD_PARAM)
		.and()
		.logout()
			.logoutUrl(Url.AUTH.LOGOUT_PROC)
			.invalidateHttpSession(true)
			.deleteCookies("JSESSIONID")
		.and()
		
		//세션관리
		.sessionManagement()
			.maximumSessions(200) 				//세션 허용 갯수
			.expiredUrl(Url.AUTH.LOGIN)		 	//세션 만료시 이동할 페이지
			.sessionRegistry(sesionRegistry())
			.maxSessionsPreventsLogin(true);	//동시 로그인 차단, false인 경우 기존 세션 만료
	}
	
	@Override
	public void configure(WebSecurity web) throws Exception {
		
		web
			.ignoring()
			.antMatchers(Constants.STATIC_RESOURCES_URL_PATTERS)
			.antMatchers(HttpMethod.GET, "/exception/**");
		super.configure(web);
	}
	
	//패스워드 암호화
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	@Bean
	public SessionRegistry sesionRegistry() {
		return new SpringSecuritySessionRegistImpl();
	}
	
	/* 관리자 아이디 파라미터 이름 */
	public static final String USERNAME_PARAM = "un";
	
	/* 관리자 비밀번호 파라미터 이름 */
	public static final String PASSWORD_PARAM = "up";

}

 

Constants.java 수정
package com.board.common;

/** 서비스에 사용되는 공통변수 */

public final class Constants {
	
	//프로젝트 패키지 이름
	public final static String APP_DEFAULT_PACKAGE_NAME = "com.board";
	
	//dao 패키지 경로
	public final static String MAPPER_PACKAGE = Constants.APP_DEFAULT_PACKAGE_NAME+".dao";
	
	//Tiles xml 경로
	public final static String[] TILES_LAYOUT_XML_PATH = {
			"WEB-INF/tiles.xml"
	};
	
	//Runtime에서 JSP의 refresh 적용 여부
	public final static boolean REFRESH_JSP_ON_RUNTIME = true;
	
	/** 정적 리소스 종류 */
	private final static String[] STATIC_RES = {
			 "/js"
			,"/css"
			,"/images"
			,"/favicon"
			,"/template"
			,"/font"
			,"/robots.txt"
			,"/favicon.ico"
	};
	
	/** 정적 리소스 매핑 URL 패턴 (위에꺼랑 순서 맞아야함) */
	public final static String[] STATIC_RESOURCES_URL_PATTERS = {
			 STATIC_RES[0]+"/**"
			,STATIC_RES[1]+"/**"
			,STATIC_RES[2]+"/**"
			,STATIC_RES[3]+"/**"
			,STATIC_RES[4]+"/**"
			,STATIC_RES[5]+"/**"
			,STATIC_RES[6]
			,STATIC_RES[7]+"/**"
	};
	
}

 

Url.java 수정
package com.board.common;

/* api url 정의 */
public final class Url {
	public static final String TILES_ROOT = "/tiles/view";
	public static final String TILES_AJAX = "/tiles/ajax";
	
	/* 로그인 */
	public static final class AUTH {
		
		/* 로그인 url */
		public static final String LOGIN = "/auth/login";
		
		/* 로그인 jsp */
		public static final String LOGIN_JSP = TILES_ROOT + "/auth/login";
		
		/* 회원가입 url */
		public static final String JOIN = "/auth/join";
		
		/* 회원가입 jsp */
		public static final String JOIN_JSP = TILES_ROOT + "/auth/join";
	
		/* 사용자 등록 */
		public static final String INSERT_USER = "/auth/insertUser";
		
		/* 로그인 인증 요청 */
		public static final String LOGIN_PROC = "/auth/login-proc";
		
		/* 로그아웃 요청 */
		public static final String LOGOUT_PROC = "/auth/logout-proc";
		
	}
	
	/* 메인 화면 */
	public static final class MAIN {
		/* 로그인 url */
		public static final String MAIN = "/";
		
		/* 로그인 jsp */
		public static final String MAIN_JSP = TILES_ROOT + "/main/list";
	}
	
}

 

admin 프로젝트의 LoginController 수정

 

LoginController.java
package com.board.controller;

import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.board.common.Url;
import com.board.entity.UserInfo;
import com.board.service.LoginService;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
public class LoginController {

	@Autowired
	LoginService loginService;
	
	//로그인 화면
	@GetMapping(value= {Url.AUTH.LOGIN})
	public String login() {
		
		return Url.AUTH.LOGIN_JSP;
	}
	
	//회원가입 화면
	@GetMapping(Url.AUTH.JOIN)
	public String join() {
		return Url.AUTH.JOIN_JSP;
	}
	
	//메인화면
	@GetMapping(Url.MAIN.MAIN)
	public String main() {
		return Url.MAIN.MAIN_JSP;
	}
	
	//사용자 등록
	@PostMapping(Url.AUTH.INSERT_USER)
	@ResponseBody
	public Map<String, Object> insertUser(@ModelAttribute UserInfo userInfo) {
		
		//회원 등록
		return loginService.checkLoginInsert(userInfo);
	}
	
}

 

login.jsp, login-js,jsp 수정

 

login.jsp
<%@ page language="java" session="true" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ include file="/WEB-INF/template/constants.jsp"%>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<link rel="stylesheet" type="text/css" href="${ctxPath}/css/loginForm.css"/>

<div class="wrapper fadeInDown">
    <div id="formContent">
        <!-- Tabs Titles -->

        <!-- Icon -->
        <div class="fadeIn first">
            로그인
        </div>

        <!-- Login Form -->
        <form>
            <input type="text" id="loginId" class="fadeIn second" name="un" placeholder="아이디를 입력해주세요" required>
            <input type="text" id="loginPw" class="fadeIn third" name="up" placeholder="비밀번호를 입력해주세요" required>
            <input type="button" class="fadeIn fourth" value="Log In" onclick="loginSubmit()">
        </form>

        <!-- Remind Passowrd -->
        <div id="formFooter">
            <a class="underlineHover" href="/auth/join">회원가입</a>
        </div>

    </div>
</div>

 

login-js.jsp
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<script>

	//로그인 submit
	function loginSubmit(){
		
		var params = {
			 'un' : $.trim($("#loginId").val())
			,'up' : $("#loginPw").val()
		}
		
		console.log(params);
		
		$.ajax({
	         type : 'POST'
	        ,url : '/auth/login-proc'
	        ,dataType : 'json'
	        ,data : params 
	        ,success : function(result) {
				console.log(result);
				if(result.resultCode != "00"){
					alert(result.resultMessage);
				}
				
				else{
					location.href=result.targetUrl;
				}
				
	        },
	        error: function(request, status, error) {
	          
	        }
	    }) 
	}

</script>

 

join.jsp
<%@ page language="java" session="true" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ include file="/WEB-INF/template/constants.jsp"%>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<link rel="stylesheet" type="text/css" href="${ctxPath}/css/loginForm.css"/>

<div class="wrapper">
  <div id="formContent">
    <!-- Tabs Titles -->

    <!-- Icon -->
    <div class="fadeIn first">
      회원가입
    </div>

    <!-- Login Form -->
    <form>
      <input type="text" id="userId" class="fadeIn second" name="login" placeholder="아이디를 입력해주세요." required>
      <input type="text" id="password" class="fadeIn third" name="login" placeholder="비밀번호를 입력해주세요." required>
      <input type="text" id="userName" class="fadeIn third" name="login" placeholder="이름을 입력해주세요.">
      <input type="text" id="email" class="fadeIn third" name="login" placeholder="이메일을 입력해주세요.">
      <input type="text" id="handPhoneNo" class="fadeIn third" name="login" placeholder="핸드폰번호를 입력해주세요.">
      <input type="button" class="fadeIn fourth" value="Join" onclick="join()">
    </form>

    <!-- Remind Passowrd -->
    <div id="formFooter">
      <a class="underlineHover" href="/auth/login">뒤로가기</a>
    </div>

  </div>
</div>

 

join-js.jsp
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<script>

	//로그인 submit
	function join(){
		
		var params = {
			  'userId' : $("#userId").val()
			 ,'password' : $("#password").val()
			 ,'userName' : $("#userName").val()
			 ,'email' : $("#email").val()
			 ,'handPhoneNo' : $("#handPhoneNo").val() 
			 
		}
		
		console.log(params);
		
		$.ajax({
	         type : 'POST'
	        ,url : '/auth/insertUser'
	        ,dataType : 'json'
	        ,data : params 
	        ,success : function(result) {
	        	alert(result.resultMsg);
	        	if(result.resultCode == '00'){
	        		location.href="/auth/login";
	        	}
	        },
	        error: function(request, status, error) {
	          
	        }
	    }) 
	}
</script>

 

views 아래 main폴더 생성후 list.jsp, list-js.jsp 생성

 

list.jsp
<%@ page language="java" session="true" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ include file="/WEB-INF/template/constants.jsp"%>

<body>
	메인입니다. <br>
	<button onclick="location.href='/auth/logout-proc'">로그아웃</button>
</body>

 

list-js.jsp
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<script>

</script>

 

로그인화면

회원등록 화면

 

 

Join버튼 클릭

 

 

db에 저장되어있는지 확인

 

로그인시도 (아이디또는 패스워드 일부러 틀렸을때)

 

해당계정에 권한이 없을경우

 

로그인 성공시

->로그아웃 버튼 클릭시 로그아웃이 되는것을 볼수있습니다.

 

다음포스팅 에서는 게시판을 개발해서 적용해보겠습니다. 감사합니다.

복사했습니다!