최초 커밋
commit
cbbd2497f4
@ -0,0 +1,204 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>cokr.xit</groupId>
|
||||
<artifactId>xit-security</artifactId>
|
||||
<version>23.04.01</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>xit-security</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<java.version>1.8</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
|
||||
<spring.maven.artifact.version>5.3.20</spring.maven.artifact.version>
|
||||
<org.egovframe.rte.version>4.1.0</org.egovframe.rte.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>mvn2s</id>
|
||||
<url>https://repo1.maven.org/maven2/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>egovframe</id>
|
||||
<url>http://maven.egovframe.kr:8080/maven/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>egovframe2</id>
|
||||
<url>https://www.egovframe.go.kr/maven/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.egovframe.rte</groupId>
|
||||
<artifactId>org.egovframe.rte.fdl.security</artifactId>
|
||||
<version>${org.egovframe.rte.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cokr.xit</groupId>
|
||||
<artifactId>xit-user</artifactId>
|
||||
<version>23.04.01</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
<artifactId>mariadb-java-client</artifactId>
|
||||
<version>2.7.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>install</defaultGoal>
|
||||
<directory>${basedir}/target</directory>
|
||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||
|
||||
<resources>
|
||||
<resource><directory>${basedir}/src/main/resources</directory></resource>
|
||||
</resources>
|
||||
|
||||
<testResources>
|
||||
<testResource><directory>${basedir}/src/test/resources</directory></testResource>
|
||||
<testResource><directory>${basedir}/src/main/resources</directory></testResource>
|
||||
</testResources>
|
||||
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.tomcat.maven</groupId>
|
||||
<artifactId>tomcat7-maven-plugin</artifactId>
|
||||
<version>2.2</version>
|
||||
<configuration>
|
||||
<port>80</port>
|
||||
<path>/</path>
|
||||
<systemProperties>
|
||||
<JAVA_OPTS>-Xms256m -Xmx768m -XX:MaxPermSize=256m</JAVA_OPTS>
|
||||
</systemProperties>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>hibernate3-maven-plugin</artifactId>
|
||||
<version>2.1</version>
|
||||
<configuration>
|
||||
<components>
|
||||
<component>
|
||||
<name>hbm2ddl</name>
|
||||
<implementation>annotationconfiguration</implementation>
|
||||
</component>
|
||||
</components>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>2.3.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<!-- EMMA -->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>emma-maven-plugin</artifactId>
|
||||
<version>1.0-alpha-3</version>
|
||||
</plugin>
|
||||
<!-- PMD manven plugin -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-pmd-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*.class</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- EMMA -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
<reportFormat>xml</reportFormat>
|
||||
<excludes>
|
||||
<exclude>**/Abstract*.java</exclude>
|
||||
<exclude>**/*Suite.java</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*Test.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>emma-maven-plugin</artifactId>
|
||||
<inherited>true</inherited>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Javadoc -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,234 @@
|
||||
package cokr.xit.base.security;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import cokr.xit.foundation.Assert;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
import cokr.xit.foundation.data.StringMap;
|
||||
|
||||
/**권한 정보, 사용자의 역할(Role)
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class Authority implements GrantedAuthority {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**권한 유형
|
||||
* @author mjkhan
|
||||
*/
|
||||
public static enum Type {
|
||||
/** 수퍼 권한: 시스템 관리자 권한 */
|
||||
SUPER,
|
||||
/** 내재적 권한: 시스템 사용자 권한, 로그인하지 않은 사용자 권한 */
|
||||
IMPLICIT,
|
||||
/** 시스템 정의 권한 */
|
||||
SYS_DEFINED;
|
||||
|
||||
/**현재 권한 유형이 내장된 유형(SUPER, IMPLICIT)인지 반환한다.
|
||||
* @return 권한 유형의 내장 여부
|
||||
* <ul><li>내장 유형이면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean isBuiltIn() {
|
||||
return !SYS_DEFINED.equals(this);
|
||||
}
|
||||
}
|
||||
|
||||
private int type;
|
||||
private String
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
infoScope,
|
||||
userInfoScope;
|
||||
private List<String> actions;
|
||||
private Date createdAt;
|
||||
|
||||
/**{@link Type 권한 유형} 코드를 반환한다.
|
||||
* @return 권한 유형 코드
|
||||
*/
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**{@link Type 권한 유형}을 반환한다.
|
||||
* @return 권한 유형
|
||||
*/
|
||||
public Type type() {
|
||||
return Type.values()[type];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthority() {
|
||||
return getId();
|
||||
}
|
||||
|
||||
/**권한 id를 반환한다.
|
||||
* @return 권한 id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**권한 id를 설정한다.
|
||||
* @param id 권한 id
|
||||
*/
|
||||
public Authority setId(String id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**권한 이름을 반환한다.
|
||||
* @return 권한 이름
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**권한 이름을 설정한다.
|
||||
* @param name 권한 이름
|
||||
*/
|
||||
public Authority setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**설명을 반환한다.
|
||||
* @return 설명
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**설명을 설정한다.
|
||||
* @param description 설명
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**접근할 수 있는 업무정보 범위를 반환한다.
|
||||
* @return 접근할 수 있는 업무정보 범위
|
||||
* <ul><li>ALL - 모든 정보</li>
|
||||
* <li>SELF - 사용자가 등록한 정보</li>
|
||||
* </ul>
|
||||
*/
|
||||
public String getInfoScope() {
|
||||
return infoScope;
|
||||
}
|
||||
|
||||
/**접근할 수 있는 업무정보 범위를 설정한다.
|
||||
* @param infoScope 접근할 수 있는 업무정보 범위
|
||||
* <ul><li>ALL - 모든 정보</li>
|
||||
* <li>SELF - 사용자가 등록한 정보</li>
|
||||
* </ul>
|
||||
*/
|
||||
public Authority setInfoScope(String infoScope) {
|
||||
this.infoScope = infoScope;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**접근할 수 있는 사용자정보 범위를 반환한다.
|
||||
* @return 접근할 수 있는 사용자정보 범위
|
||||
* <ul><li>ALL - 모든 사용자정보</li>
|
||||
* <li>SELF - 사용자 자신의 정보</li>
|
||||
* </ul>
|
||||
*/
|
||||
public String getUserInfoScope() {
|
||||
return userInfoScope;
|
||||
}
|
||||
|
||||
/**접근할 수 있는 사용자정보 범위를 설정한다.
|
||||
* @param userInfoScope 접근할 수 있는 사용자정보 범위
|
||||
* <ul><li>ALL - 모든 사용자정보</li>
|
||||
* <li>SELF - 사용자 자신의 정보</li>
|
||||
* </ul>
|
||||
*/
|
||||
public Authority setUserInfoScope(String userInfoScope) {
|
||||
this.userInfoScope = userInfoScope;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**등록 일시를 반환한다.
|
||||
* @return 등록 일시
|
||||
*/
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
/**등록 일시를 설정한다.
|
||||
* @param createdAt 등록 일시
|
||||
*/
|
||||
public void setCreatedAt(Date createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
/**실행기능(URL)을 반환한다.
|
||||
* @return 실행기능(URL)
|
||||
*/
|
||||
public List<String> getActions() {
|
||||
return actions != null ? actions : Collections.emptyList();
|
||||
}
|
||||
|
||||
/**실행기능(URL)을 설정한다.
|
||||
* @param actions 실행기능(URL)
|
||||
*/
|
||||
public void setActions(List<String> actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
private StringMap<String> infoScopes;
|
||||
|
||||
/**정보 접근 범위를 반환한다.
|
||||
* @return 정보 접근 범위
|
||||
*/
|
||||
public Map<String, String> getInfoScopes() {
|
||||
return Assert.ifEmpty(infoScopes, Collections::emptyMap);
|
||||
}
|
||||
|
||||
/**정보 접근 범위를 설정한다.
|
||||
* @param infoScopes 정보 접근 범위
|
||||
*/
|
||||
public void setInfoScopes(List<DataObject> infoScopes) {
|
||||
if (this.infoScopes != null)
|
||||
this.infoScopes.clear();
|
||||
if (Assert.isEmpty(infoScopes))
|
||||
return;
|
||||
|
||||
if (this.infoScopes == null)
|
||||
this.infoScopes = new StringMap<>();
|
||||
|
||||
infoScopes.forEach(row -> this.infoScopes.put(row.string("INF_TYPE"), row.string("INF_SCP")));
|
||||
}
|
||||
|
||||
/**지정하는 정보유형의 접근 범위를 반환한다.
|
||||
* @param infoType 정보 유형
|
||||
* @return 접근 범위
|
||||
*/
|
||||
public String getInfoScope(String infoType) {
|
||||
return Assert.ifEmpty(infoScopes != null ? infoScopes.get(infoType) : null, () -> "none");
|
||||
}
|
||||
|
||||
/**action을 실행할 권한이 있는지 반환한다.
|
||||
* @param action 실행할 기능(URL)
|
||||
* @return
|
||||
* <ul><li>기능을 실행할 권한이 있으면 true</li>
|
||||
* <li>기능을 실행할 권한이 없으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean isGranted(String action) {
|
||||
if (Type.SUPER.equals(type())) return true;
|
||||
|
||||
return getActions().contains(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s{id:'%s', name:'%s'}", getClass().getSimpleName(), getId(), getName());
|
||||
}
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
package cokr.xit.base.security;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import cokr.xit.foundation.UserInfo;
|
||||
|
||||
/**현재 접속한 사용자의 정보를 갖는 객체.<br />
|
||||
* 권한 정보를 추가하여, 사용자가 특정 기능을 실행할 권한이 있는지 제공한다.
|
||||
*/
|
||||
public class SecuredUserInfo extends UserInfo implements UserDetails {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**현재 접속한 사용자의 정보를 찾는 객체
|
||||
* @author mjkhan
|
||||
*/
|
||||
@Component(UserInfo.SEC_NAME)
|
||||
public static class Provider extends UserInfo.Provider {
|
||||
@Override
|
||||
public UserInfo currentUser() {
|
||||
return userInfo == null ? get(SecurityContextHolder.getContext().getAuthentication()) : (UserInfo)userInfo;
|
||||
}
|
||||
|
||||
private UserInfo get(Authentication authentication) {
|
||||
Object obj = authentication != null ? authentication.getPrincipal() : null;
|
||||
return obj instanceof SecuredUserInfo ? (UserInfo)obj : SecuredUserInfo.unknown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserInfo(UserInfo userInfo) {
|
||||
if (!(userInfo instanceof SecuredUserInfo))
|
||||
throw new IllegalArgumentException("userInfo is not a SecuredUserInfo");
|
||||
super.setUserInfo(userInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**인증되지 않은 사용자 정보
|
||||
*/
|
||||
public static final SecuredUserInfo unknown = new SecuredUserInfo().seal();
|
||||
|
||||
private List<Authority> authorities;
|
||||
private boolean sealed;
|
||||
|
||||
@Override
|
||||
public List<Authority> getAuthorities() {
|
||||
return authorities != null ? authorities : Collections.emptyList();
|
||||
}
|
||||
|
||||
/**사용자에게 허용된 권한을 설정한다.
|
||||
* @param authorities 허용된 권한 목록
|
||||
*/
|
||||
public void setAuthorities(List<Authority> authorities) {
|
||||
notSealed().authorities = authorities;
|
||||
}
|
||||
|
||||
/**사용자에게 action을 실행할 권한이 있는지 반환한다.
|
||||
* @param action 실행할 기능(URL)
|
||||
* @return
|
||||
* <ul><li>기능을 실행할 권한이 있으면 true</li>
|
||||
* <li>기능을 실행할 권한이 없으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean isGranted(String action) {
|
||||
if (authorities != null && !authorities.isEmpty()) {
|
||||
for (Authority authority: authorities) {
|
||||
if (authority.isGranted(action))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**사용자가 지정한 아이디의 권한이 있는지 반환한다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return
|
||||
* <ul><li>지정한 아이디의 권한이 있으면 true</li>
|
||||
* <li>지정한 아이디의 권한이 없으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean hasAuthorities(String... authIDs) {
|
||||
if (authIDs == null || authIDs.length < 1) return false;
|
||||
|
||||
for (Authority authority: getAuthorities()) {
|
||||
String authorityID = authority.getId();
|
||||
for (String authID: authIDs) {
|
||||
if (authorityID.equals(authID))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAccessibleActions() {
|
||||
List<Authority> authorities = getAuthorities();
|
||||
boolean admin = authorities.stream()
|
||||
.filter(auth -> Authority.Type.SUPER.equals(auth.type()))
|
||||
.count() > 0;
|
||||
if (admin) {
|
||||
return ALL_ACTIONS;
|
||||
} else {
|
||||
return authorities.stream()
|
||||
.flatMap(auth -> auth.getActions().stream())
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
/**지정하는 아이디의 권한의 정보접근 범위를 반환한다.
|
||||
* @param authID 권한 아이디
|
||||
* @return 지정하는 아이디의 권한의 정보접근 범위
|
||||
*/
|
||||
public String getInfoScope(String authID) {
|
||||
for (Authority authority: getAuthorities()) {
|
||||
if (authority.getId().equals(authID))
|
||||
return authority.getInfoScope();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private SecuredUserInfo seal() {
|
||||
sealed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
private SecuredUserInfo notSealed() {
|
||||
if (sealed)
|
||||
throw new IllegalStateException(this + " is sealed");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s('%s', '%s')", getClass().getSimpleName(), getId(), getName());
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package cokr.xit.base.security.access;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import cokr.xit.base.security.Authority;
|
||||
import cokr.xit.base.security.access.dao.AuthorityMapper;
|
||||
import cokr.xit.foundation.AbstractComponent;
|
||||
|
||||
/**애플리케이션이 정의하거나 등록한 권한과 각 권한이 실행할 수 있는 기능(URL)들을 로드하여
|
||||
* 사용자의 권한 체크에 정보를 제공한다.<br />
|
||||
* AccessContext는 애플리케이션이 로드될 때 이 정보들을 가져온다.
|
||||
* @author mjkhan
|
||||
*/
|
||||
@Component("accessContext")
|
||||
public class AccessContext extends AbstractComponent implements ApplicationContextAware {
|
||||
/** 권한 인덱스 */
|
||||
protected Map<String, Authority> authorityIndex;
|
||||
/** 내재적 권한 목록 */
|
||||
protected List<Authority> implicits;
|
||||
/** 권한 정보 DAO */
|
||||
@Resource(name="authorityMapper")
|
||||
protected AuthorityMapper authorityMapper;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
loadAuthorities();
|
||||
}
|
||||
|
||||
/**애플리케이션의 모든 권한과 각 권한이 실행할 수 있는 기능(URL)을 로드한다.
|
||||
*/
|
||||
public void loadAuthorities() {
|
||||
List<Authority> authorities = authorityMapper.getAuthorities();
|
||||
authorityIndex = authorities.stream()
|
||||
.collect(Collectors.toMap(Authority::getId, auth -> auth));
|
||||
if (authorityIndex.isEmpty()) return;
|
||||
|
||||
implicits = authorities.stream()
|
||||
.filter(authority -> Authority.Type.IMPLICIT.equals(authority.type()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
authorityMapper.getActionList().stream()
|
||||
.collect(Collectors.groupingBy(row -> row.string("AUTH_ID")))
|
||||
.forEach((authID, actions) -> {
|
||||
List<String> actionList = actions.stream()
|
||||
.map(action -> action.string("ACTION"))
|
||||
.collect(Collectors.toList());
|
||||
Authority authority = authorityIndex.get(authID);
|
||||
if (authority != null)
|
||||
authority.setActions(actionList);
|
||||
});
|
||||
}
|
||||
|
||||
/**지정하는 권한들을 반환한다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 권한 목록
|
||||
*/
|
||||
public List<Authority> getAuthorities(List<String> authIDs) {
|
||||
if (isEmpty(authIDs) || isEmpty(authorityIndex))
|
||||
return Collections.emptyList();
|
||||
|
||||
return authorityIndex.entrySet().stream()
|
||||
.filter(entry -> authIDs.contains(entry.getKey()))
|
||||
.map(Entry::getValue)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**내재적 권한 목록을 반환한다.
|
||||
* @return 내재적 권한 목록
|
||||
*/
|
||||
public List<Authority> getImplicits() {
|
||||
return ifEmpty(implicits, Collections::emptyList);
|
||||
}
|
||||
|
||||
/**지정하는 권한이 실행할 수 있는 기능(URL)을 반환한다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 실행 기능 목록
|
||||
*/
|
||||
public List<String> getActions(List<String> authIDs) {
|
||||
return getAuthorities(authIDs).stream()
|
||||
.flatMap(authority -> authority.getActions().stream())
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package cokr.xit.base.security.access;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**기능 그룹
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class ActionGroup {
|
||||
private String
|
||||
id,
|
||||
name,
|
||||
description;
|
||||
private Date createdAt;
|
||||
|
||||
/**id를 반환한다.
|
||||
* @return id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**id를 설정한다.
|
||||
* @param id id
|
||||
*/
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**이름을 반환한다.
|
||||
* @return 이름
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**이름을 설정한다.
|
||||
* @param name 이름
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**설명을 반환한다.
|
||||
* @return 설명
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**설명을 설정한다.
|
||||
* @param description 설명
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**등록 일자를 반환한다.
|
||||
* @return 등록 일자
|
||||
*/
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
/**등록 일자를 설정한다.
|
||||
* @param createdAt 등록 일자
|
||||
*/
|
||||
public void setCreatedAt(Date createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s('%s', '%s')", getClass().getSimpleName(), getId(), getName());
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package cokr.xit.base.security.access;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import cokr.xit.base.security.Authority;
|
||||
import cokr.xit.base.security.SecuredUserInfo;
|
||||
import cokr.xit.foundation.AbstractComponent;
|
||||
import cokr.xit.foundation.Access;
|
||||
|
||||
/**애플리케이션 접근 제어자.<br />
|
||||
* 사용자가 애플리케이션의 기능을 실행할 수 있는지 판단한다.
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class ApplicationAccess extends AbstractComponent implements AccessDecisionVoter<Object> {
|
||||
private boolean controlAccess;
|
||||
/** 권한별 가용 기능(URL) */
|
||||
@Resource(name="accessContext")
|
||||
protected AccessContext accessContext;
|
||||
|
||||
/**접근 제어를 사용할지 설정한다.
|
||||
* @param controlAccess 접근 제어 사용 여부
|
||||
* <ul><li>접근 제어를 사용하면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void setControlAccess(boolean controlAccess) {
|
||||
this.controlAccess = controlAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vote(Authentication authentication, Object obj, Collection<ConfigAttribute> attributes) {
|
||||
if (!controlAccess) return ACCESS_GRANTED;
|
||||
|
||||
String action = Access.current().getAction();
|
||||
if (isEmpty(action))
|
||||
return ACCESS_GRANTED;
|
||||
|
||||
SecuredUserInfo userInfo = currentUser();
|
||||
if (userInfo.isGranted(action))
|
||||
return ACCESS_GRANTED;
|
||||
|
||||
for (Authority authority: accessContext.getImplicits())
|
||||
if (authority.isGranted(action))
|
||||
return ACCESS_GRANTED;
|
||||
|
||||
return ACCESS_DENIED;
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package cokr.xit.base.security.access.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
|
||||
|
||||
import cokr.xit.base.security.access.ActionGroup;
|
||||
import cokr.xit.base.security.access.service.ActionQuery;
|
||||
import cokr.xit.foundation.component.AbstractMapper;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**기능 그룹 관리 DAO
|
||||
* @author mjkhan
|
||||
*/
|
||||
@Mapper("actionGroupMapper")
|
||||
public interface ActionGroupMapper extends AbstractMapper {
|
||||
/**주어진 조건에 따라 기능 그룹 목록을 조회한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>actionGroupName - 기능 그룹 이름</li>
|
||||
* <li>그 외는 기능 그룹 아이디</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param fetchSize 한 번에 가져올 기능 그룹수
|
||||
* @return 기능 그룹 목록
|
||||
*/
|
||||
List<DataObject> getGroupList(ActionQuery req);
|
||||
|
||||
/**지정하는 기능 그룹을 가져온다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 기능 그룹
|
||||
*/
|
||||
List<ActionGroup> getGroups(ActionQuery req);
|
||||
|
||||
/**지정하는 기능 그룹을 가져온다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 기능 그룹
|
||||
*/
|
||||
default List<ActionGroup> getGroups(String... groupIDs) {
|
||||
ActionQuery req = new ActionQuery().setGroupIDs(groupIDs);
|
||||
return getGroups(req);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹을 가져온다.
|
||||
* @param groupID 기능 그룹 아이디
|
||||
* @return 기능 그룹
|
||||
*/
|
||||
default ActionGroup getGroup(String groupID) {
|
||||
List<ActionGroup> groups = getGroups(groupID);
|
||||
return !groups.isEmpty() ? groups.get(0) : null;
|
||||
}
|
||||
|
||||
/**기능 그룹을 등록한다.
|
||||
* @param group 기능 그룹
|
||||
* @return 등록 여부
|
||||
* <ul><li>등록됐으면 true</li>
|
||||
* <li>그렇지 않으며 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
int insertGroup(ActionGroup group);
|
||||
|
||||
/**기능 그룹을 수정한다.
|
||||
* @param group 기능 그룹
|
||||
* @return 수정 여부
|
||||
* <ul><li>수정됐으면 true</li>
|
||||
* <li>그렇지 않으며 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
int updateGroup(ActionGroup group);
|
||||
|
||||
/**지정하는 기능 그룹을 제거한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int removeGroups(Map<String, ?> params);
|
||||
|
||||
/**지정하는 기능 그룹을 제거한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int removeGroups(String... groupIDs) {
|
||||
if (isEmpty(groupIDs)) return 0;
|
||||
|
||||
removeActions(groupIDs, null);
|
||||
|
||||
DataObject params = params()
|
||||
.set("groupIDs", ifEmpty(groupIDs, () -> null))
|
||||
.set("currentUser", currentUser());
|
||||
return removeGroups(params);
|
||||
}
|
||||
|
||||
/**지정하는 그룹의 기능 목록을 조회한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 기능 목록
|
||||
*/
|
||||
List<DataObject> getActionList(ActionQuery req);
|
||||
|
||||
/**지정하는 그룹의 기능 목록을 조회한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 기능 목록
|
||||
*/
|
||||
default List<DataObject> getActionList(String... groupIDs) {
|
||||
return getActionList(new ActionQuery().setGroupIDs(groupIDs));
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹에 기능들을 추가한다.
|
||||
* @param groupID 그룹 아이디
|
||||
* @param actions 기능(URL)
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int addActions(Map<String, ?> params);
|
||||
|
||||
/**지정하는 기능 그룹에 기능들을 추가한다.
|
||||
* @param groupID 그룹 아이디
|
||||
* @param actions 기능(URL)
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int addActions(String groupID, String... actions) {
|
||||
if (isEmpty(groupID) || isEmpty(actions)) return 0;
|
||||
|
||||
DataObject params = params()
|
||||
.set("groupID", groupID)
|
||||
.set("actions", ifEmpty(actions, () -> null))
|
||||
.set("currentUser", currentUser());
|
||||
return addActions(params);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹의 기능을 제거한다.
|
||||
* @param groupID 기능 그룹 아이디
|
||||
* @param actions 기능
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int removeActions(Map<String, ?> params);
|
||||
|
||||
/**지정하는 기능 그룹의 기능을 제거한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @param actions 기능
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int removeActions(String[] groupIDs, String[] actions) {
|
||||
if (isEmpty(groupIDs) && isEmpty(actions)) return 0;
|
||||
|
||||
DataObject params = params()
|
||||
.set("groupIDs", ifEmpty(groupIDs, () -> null))
|
||||
.set("actions", ifEmpty(actions, () -> null))
|
||||
.set("currentUser", currentUser());
|
||||
return removeActions(params);
|
||||
}
|
||||
}
|
@ -0,0 +1,240 @@
|
||||
package cokr.xit.base.security.access.dao;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.egovframe.rte.psl.dataaccess.mapper.Mapper;
|
||||
|
||||
import cokr.xit.base.security.Authority;
|
||||
import cokr.xit.base.security.access.service.AuthorityQuery;
|
||||
import cokr.xit.foundation.component.AbstractMapper;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**권한 정보 관리 DAO
|
||||
* @author mjkhan
|
||||
*/
|
||||
@Mapper("authorityMapper")
|
||||
public interface AuthorityMapper extends AbstractMapper {
|
||||
/**주어진 조건의 권한 목록을 조회한다.
|
||||
* @return 권한 목록
|
||||
*/
|
||||
List<DataObject> getAuthorityList(AuthorityQuery req);
|
||||
|
||||
/**주어진 조건의 권한들을 가져온다.
|
||||
* @return 권한 목록
|
||||
*/
|
||||
List<Authority> getAuthorities(AuthorityQuery req);
|
||||
|
||||
/**지정하는 아이디의 권한들을 가져온다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 권한 목록
|
||||
*/
|
||||
default List<Authority> getAuthorities(String... authIDs) {
|
||||
return getAuthorities(new AuthorityQuery().setAuthIDs(authIDs));
|
||||
}
|
||||
|
||||
/**지정하는 아이디의 권한을 가져온다.
|
||||
* @param authID 권한 아이디
|
||||
* @return 권한
|
||||
*/
|
||||
default Authority getAuthority(String authID) {
|
||||
List<Authority> authorities = getAuthorities(authID);
|
||||
return !authorities.isEmpty() ? authorities.get(0) : null;
|
||||
}
|
||||
|
||||
/**권한을 등록한다.
|
||||
* @param authority 권한
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int insertAuthority(Authority authority);
|
||||
|
||||
/**권한을 수정한다.
|
||||
* @param authority 권한
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int updateAuthority(Authority authority);
|
||||
|
||||
/**지정하는 조건의 권한을 삭제한다.
|
||||
* @param params 삭제 조건
|
||||
* <pre><code> {
|
||||
* "authIDs": 권한 아이디
|
||||
* }</code></pre>
|
||||
* @return
|
||||
*/
|
||||
int removeAuthorities(Map<String, ?> params);
|
||||
|
||||
/**지정하는 권한들을 삭제한다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int removeAuthorities(String... authIDs) {
|
||||
List<Authority> authorities = getAuthorities(authIDs);
|
||||
if (authorities.stream().filter(authority -> authority.type().isBuiltIn()).count() > 0)
|
||||
throw new RuntimeException("내장된 권한은 삭제할 수 없습니다.");
|
||||
|
||||
removeActionGroups(authIDs, null);
|
||||
removeUsers(authIDs, null);
|
||||
return removeAuthorities(params().set("authIDs", authIDs));
|
||||
}
|
||||
|
||||
/**지정하는 권한의 기능 그룹 목록을 조회한다.
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param fetchSize 한 번에 가져올 기능 그룹수
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 권한별 기능 그룹 목록
|
||||
*/
|
||||
List<DataObject> getActionGroupList(AuthorityQuery req);
|
||||
|
||||
/**지정하는 권한에 기능 그룹들을 추가한다.
|
||||
* @param params 권한, 기능그룹 아이디
|
||||
* <pre><code> {
|
||||
* "authID": 권한 아이디,
|
||||
* "groupIDs": 기능그룹 아이디(배열)
|
||||
* }</code></pre>
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int addActionGroups(Map<String, ?> params);
|
||||
|
||||
/**지정하는 권한에 기능 그룹들을 추가한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int addActionGroups(String authID, String... groupIDs) {
|
||||
return addActionGroups(
|
||||
params()
|
||||
.set("authID", authID)
|
||||
.set("groupIDs", groupIDs)
|
||||
);
|
||||
}
|
||||
|
||||
/**지정한 권한의 기능 그룹들을 삭제한다.
|
||||
* @param params 삭제 조건
|
||||
* <pre><code> {
|
||||
* "authIDs": 권한 아이디(배열),
|
||||
* "groupIDs": 기능그룹 아이디(배열)
|
||||
* }</code></pre>
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int removeActionGroups(Map<String, ?> params);
|
||||
|
||||
/**지정한 권한의 기능 그룹들을 삭제한다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int removeActionGroups(String[] authIDs, String[] groupIDs) {
|
||||
DataObject params = params()
|
||||
.set("authIDs", ifEmpty(authIDs, () -> null))
|
||||
.set("groupIDs", ifEmpty(groupIDs, () -> null));
|
||||
return removeActionGroups(params);
|
||||
}
|
||||
|
||||
/**지정하는 권한에서 기능 그룹들을 삭제한다.<br />
|
||||
* 기능 그룹을 지정하지 않으면 해당 권한의 모든 기능 그룹을 삭제한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int removeActionGroups(String authID, String... groupIDs) {
|
||||
return removeActionGroups(new String[] {authID}, groupIDs);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹들을 삭제한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int removeActionGroups(String... groupIDs) {
|
||||
return removeActionGroups((String[])null, groupIDs);
|
||||
}
|
||||
|
||||
/**권한별 기능 그룹, 기능 목록을 가져온다.
|
||||
* @return 권한별 기능 그룹, 기능 목록
|
||||
*/
|
||||
List<DataObject> getActionList();
|
||||
|
||||
/**지정하는 권한의 사용자를 조회한다.
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param fetchSize 한 번에 가져올 사용자 정보수
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 사용자 목록
|
||||
*/
|
||||
List<DataObject> getUserList(AuthorityQuery req);
|
||||
|
||||
/**지정하는 사용자의 권한 목록을 조회한다.
|
||||
* @param params 사용자 조회 조건
|
||||
* <pre><code> {
|
||||
* "userIDs": 사용자 아이디(배열)
|
||||
* }</code></pre>
|
||||
* @return 권한 목록
|
||||
*/
|
||||
List<DataObject> getUserAuths(Map<String, ?> params);
|
||||
|
||||
/**지정하는 사용자의 권한 목록을 조회한다.
|
||||
* @param userID 사용자 아이디
|
||||
* @return 권한 목록
|
||||
*/
|
||||
default List<String> getUserAuths(String userID) {
|
||||
List<DataObject> list = getUserAuths(params().set("userIDs", Arrays.asList(userID)));
|
||||
return list.stream()
|
||||
.map(row -> row.string("AUTH_ID"))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**지정하는 권한에 사용자를 추가한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int addUsers(Map<String, ?> params);
|
||||
|
||||
/**지정하는 권한에 사용자를 추가한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int addUsers(String authID, String... userIDs) {
|
||||
return addUsers(
|
||||
params()
|
||||
.set("authID", authID)
|
||||
.set("userIDs", userIDs)
|
||||
);
|
||||
}
|
||||
|
||||
/**지정하는 권한에서 사용자를 제거한다.<br />
|
||||
* 사용자를 지정하지 않으면 해당 권한의 모든 사용자를 제거한다.
|
||||
* @param params 사용자 제거 조건
|
||||
* <pre><code> {
|
||||
* "authIDs": 권한 아이디(배열),
|
||||
* "groupIDs": 기능그룹 아이디(배열)
|
||||
* }</code></pre>
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int removeUsers(Map<String, ?> params);
|
||||
|
||||
/**지정하는 권한에서 사용자를 제거한다.<br />
|
||||
* 사용자를 지정하지 않으면 해당 권한의 모든 사용자를 제거한다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int removeUsers(String[] authIDs, String[] userIDs) {
|
||||
return removeUsers(
|
||||
params()
|
||||
.set("authIDs", ifEmpty(authIDs, () -> null))
|
||||
.set("userIDs", ifEmpty(userIDs, () -> null))
|
||||
);
|
||||
}
|
||||
|
||||
/**지정하는 권한에서 사용자를 제거한다.<br />
|
||||
* 사용자를 지정하지 않으면 해당 권한의 모든 사용자를 제거한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
default int removeUsers(String authID, String... userIDs) {
|
||||
return removeUsers(new String[] {authID}, userIDs);
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
/**사용자 접근 정보 테이블 접근 객체.
|
||||
*/
|
||||
package cokr.xit.base.security.access.dao;
|
@ -0,0 +1,23 @@
|
||||
/**사용자 접근 관리.
|
||||
* <ul><li>사용자 접근 관리의 체계는 다음과 같다.<br />
|
||||
* <img src="{@docRoot}/doc-files/security-access-entities.png" alt="접근 관리 엔티티" /></li>
|
||||
* <li>그룹별 기능이란 애플리케이션이 제공하는 기능(URL)을 말한다. 다음은 그 예들이다.
|
||||
* <ul><li>/notice/list.do?...</li>
|
||||
* <li>/notice/info.do?...</li>
|
||||
* <li>/notice/process.do</li>
|
||||
* <li>/notice/cancel.do</li>
|
||||
* </ul></li>
|
||||
* <li>기능 그룹이란 기능들을 특성에 따라 그룹으로 묶은 것을 말한다. 다음은 그 예들이다.
|
||||
* <ul><li>"notice-read" 그룹 - {"/notice/list.do?...", "/notice/info.do?..."}</li>
|
||||
* <li>"notice-process" 그룹 - {"/notice/process.do", "/notice/cancel.do"}</li>
|
||||
* </ul></li>
|
||||
* <li>권한(Authority)이란 사용자에게 부여되는 역할을 말한다.<br />
|
||||
* 예) "ROLE_NOTICE" - 고지 담당자</li>
|
||||
* <li>권한은 여러 개의 기능 그룹을 부여받으며, 이를 권한별 기능 그룹이라 한다.<br />
|
||||
* 예) "ROLE_NOTICE" - {"notice-read", "notice-process"}</li>
|
||||
* <li>사용자는 여러 권한을 할당받으며 이는 권한-사용자로 관리한다.</li>
|
||||
* <li>다음은 이 체계를 위한 정보를 저장하는 데이터베이스 테이블들이다.<br />
|
||||
* <img src="{@docRoot}/doc-files/security-access-tables.png" alt="접근 관리 테이블" /></li>
|
||||
* </ul>
|
||||
*/
|
||||
package cokr.xit.base.security.access;
|
@ -0,0 +1,88 @@
|
||||
package cokr.xit.base.security.access.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cokr.xit.base.security.access.ActionGroup;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**기능 그룹 관리 서비스를 제공한다.
|
||||
* <ul><li>{@link #getGroupList(String, String, int, int) 기능 그룹 목록 조회}</li>
|
||||
* <li>{@link #getGroups(String...) 기능 그룹 가져오기}</li>
|
||||
* <li>{@link #create(ActionGroup) 기능 그룹 등록}</li>
|
||||
* <li>{@link #update(ActionGroup) 기능 그룹 수정}</li>
|
||||
* <li>{@link #remove(String...) 기능 그룹 제거}</li>
|
||||
* <li>{@link #getActionList(String...) 기능 목록 조회}</li>
|
||||
* <li>{@link #addActions(String, String...) 그룹 기능 추가}</li>
|
||||
* <li>{@link #removeActions(String, String...) 그룹 기능 제거}</li>
|
||||
* </ul>
|
||||
* @author mjkhan
|
||||
*/
|
||||
public interface ActionGroupService {
|
||||
/**주어진 조건에 따라 기능 그룹 목록을 조회한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>actionGroupName - 기능 그룹 이름</li>
|
||||
* <li>그 외는 기능 그룹 아이디</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param fetchSize 한 번에 가져올 기능 그룹수
|
||||
* @return 기능 그룹 목록
|
||||
*/
|
||||
List<DataObject> getGroupList(ActionQuery req);
|
||||
|
||||
/**지정하는 기능 그룹을 가져온다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 기능 그룹
|
||||
*/
|
||||
List<ActionGroup> getGroups(String... groupIDs);
|
||||
|
||||
/**지정하는 기능 그룹을 가져온다.
|
||||
* @param groupID 기능 그룹 아이디
|
||||
* @return 기능 그룹
|
||||
*/
|
||||
ActionGroup getGroup(String groupID);
|
||||
|
||||
/**기능 그룹을 등록한다.
|
||||
* @param group 기능 그룹
|
||||
* @return 등록 여부
|
||||
* <ul><li>등록됐으면 true</li>
|
||||
* <li>그렇지 않으며 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
boolean create(ActionGroup group);
|
||||
|
||||
/**기능 그룹을 수정한다.
|
||||
* @param group 기능 그룹
|
||||
* @return 수정 여부
|
||||
* <ul><li>수정됐으면 true</li>
|
||||
* <li>그렇지 않으며 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
boolean update(ActionGroup group);
|
||||
|
||||
/**지정하는 기능 그룹을 제거한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int remove(String... groupIDs);
|
||||
|
||||
/**지정하는 그룹의 기능 목록을 조회한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 기능 목록
|
||||
*/
|
||||
List<DataObject> getActionList(ActionQuery req);
|
||||
|
||||
/**지정하는 기능 그룹에 기능들을 추가한다.
|
||||
* @param groupID 그룹 아이디
|
||||
* @param actions 기능(URL)
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int addActions(String groupID, String... actions);
|
||||
|
||||
/**지정하는 기능 그룹의 기능을 제거한다.
|
||||
* @param groupID 기능 그룹 아이디
|
||||
* @param actions 기능
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int removeActions(String groupID, String... actions);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cokr.xit.base.security.access.service;
|
||||
|
||||
import cokr.xit.foundation.component.QueryRequest;
|
||||
|
||||
public class ActionQuery extends QueryRequest {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String[] groupIDs;
|
||||
|
||||
/**groupIDs을(를) 반환한다.
|
||||
* @return groupIDs
|
||||
*/
|
||||
public String[] getGroupIDs() {
|
||||
return groupIDs;
|
||||
}
|
||||
|
||||
/**groupIDs을(를) 설정한다.
|
||||
* @param groupIDs groupIDs
|
||||
* @return ActionQuery
|
||||
*/
|
||||
public <T extends ActionQuery> T setGroupIDs(String... groupIDs) {
|
||||
this.groupIDs = groupIDs;
|
||||
return self();
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package cokr.xit.base.security.access.service;
|
||||
|
||||
import cokr.xit.foundation.component.QueryRequest;
|
||||
|
||||
/**권한 조회 조건.
|
||||
* <ul><li>by: 조회 조건 필드 이름
|
||||
* <ul><li>authID - 권한 아이디</li>
|
||||
* <li>그 외는 권한 이름</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class AuthorityQuery extends QueryRequest {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String[] authIDs;
|
||||
private String[] userIDs;
|
||||
|
||||
/**권한 아아디를 반환한다.
|
||||
* @return 권한 아아디
|
||||
*/
|
||||
public String[] getAuthIDs() {
|
||||
return ifEmpty(authIDs, () -> null);
|
||||
}
|
||||
|
||||
/**권한 아아디를 설정한다.
|
||||
* @param authIDs 권한 아아디
|
||||
* @return AuthorityQuery
|
||||
*/
|
||||
public <T extends AuthorityQuery> T setAuthIDs(String... authIDs) {
|
||||
this.authIDs = authIDs;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**사용자 아이디를 반환한다.
|
||||
* @return userIDs 사용자 아이디
|
||||
*/
|
||||
public String[] getUserIDs() {
|
||||
return ifEmpty(userIDs, () -> null);
|
||||
}
|
||||
|
||||
/**사용자 아이디를 설정한다.
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return AuthorityQuery
|
||||
*/
|
||||
public <T extends AuthorityQuery> T setUserIDs(String[] userIDs) {
|
||||
this.userIDs = userIDs;
|
||||
return self();
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package cokr.xit.base.security.access.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cokr.xit.base.security.Authority;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**권한 정보 서비스를 제공한다.
|
||||
* <ul><li>{@link #getAuthorityList(String, String, int, int) 권한 목록 조회}</li>
|
||||
* <li>{@link #getAuthorities(String...) 권한 가져오기}</li>
|
||||
* <li>{@link #create(Authority) 권한 등록}</li>
|
||||
* <li>{@link #update(Authority) 권한 수정}</li>
|
||||
* <li>{@link #removeAuthorities(String...) 권한 제거}</li>
|
||||
* <li>{@link #getActionGroupList(int, int, String...) 권한별 기능 그룹 조회}</li>
|
||||
* <li>{@link #addActionGroups(String, String...) 권한 기능 그룹 추가}</li>
|
||||
* <li>{@link #removeActionGroups(String, String...) 권한 기능 그룹 제거}</li>
|
||||
* <li>{@link #getUserList(int, int, String...) 권한별 사용자 조회}</li>
|
||||
* <li>{@link #addUsers(String, String...) 권한 사용자 추가}</li>
|
||||
* <li>{@link #removeUsers(String, String...) 권한 사용자 제거}</li>
|
||||
* </ul>
|
||||
* @author mjkhan
|
||||
*/
|
||||
public interface AuthorityService {
|
||||
/**주어진 조건의 권한 목록을 조회한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>authID - 권한 아이디</li>
|
||||
* <li>그 외는 권한 이름</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param fetchSize 한 번에 가져올 권한 정보수
|
||||
* @return 권한 목록
|
||||
*/
|
||||
List<DataObject> getAuthorityList(AuthorityQuery req);
|
||||
|
||||
/**지정하는 권한들을 가져온다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 권한 목록
|
||||
*/
|
||||
List<Authority> getAuthorities(String... authIDs);
|
||||
|
||||
/**지정하는 권한을 가져온다.
|
||||
* @param authID 권한 아이디
|
||||
* @return 권한
|
||||
*/
|
||||
Authority getAuthority(String authID);
|
||||
|
||||
/**권한을 등록한다.
|
||||
* @param authority 권한
|
||||
* @return 등록 여부
|
||||
* <ul><li>등록됐으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
boolean create(Authority authority);
|
||||
|
||||
/**권한을 수정한다.
|
||||
* @param authority 권한
|
||||
* @return 수정 여부
|
||||
* <ul><li>수정됐으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
boolean update(Authority authority);
|
||||
|
||||
/**지정하는 권한들을 삭제한다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int removeAuthorities(String... authIDs);
|
||||
|
||||
/**지정하는 권한의 기능 그룹 목록을 조회한다.
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param fetchSize 한 번에 가져올 기능 그룹수
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 권한별 기능 그룹 목록
|
||||
*/
|
||||
List<DataObject> getActionGroupList(AuthorityQuery req);
|
||||
|
||||
/**지정하는 권한에 기능 그룹들을 추가한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int addActionGroups(String authID, String... groupIDs);
|
||||
|
||||
/**지정하는 권한에서 기능 그룹들을 삭제한다.<br />
|
||||
* 기능 그룹을 지정하지 않으면 해당 권한의 모든 기능 그룹을 삭제한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int removeActionGroups(String authID, String... groupIDs);
|
||||
|
||||
/**지정하는 권한의 사용자를 조회한다.
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param fetchSize 한 번에 가져올 사용자 정보수
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 사용자 목록
|
||||
*/
|
||||
List<DataObject> getUserList(AuthorityQuery req);
|
||||
|
||||
/**지정하는 권한에 사용자를 추가한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int addUsers(String authID, String... userIDs);
|
||||
|
||||
/**지정하는 권한에서 사용자를 제거한다.<br />
|
||||
* 사용자를 지정하지 않으면 해당 권한의 모든 사용자를 제거한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int removeUsers(String authID, String... userIDs);
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
package cokr.xit.base.security.access.service.bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import cokr.xit.base.security.access.ActionGroup;
|
||||
import cokr.xit.base.security.access.dao.ActionGroupMapper;
|
||||
import cokr.xit.base.security.access.service.ActionQuery;
|
||||
import cokr.xit.foundation.AbstractComponent;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**기능 그룹 관리 DAO
|
||||
* @author mjkhan
|
||||
*/
|
||||
@Component("actionGroupBean")
|
||||
public class ActionGroupBean extends AbstractComponent {
|
||||
@Resource(name = "actionGroupMapper")
|
||||
private ActionGroupMapper actionGroupMapper;
|
||||
|
||||
/**주어진 조건에 따라 기능 그룹 목록을 조회한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>actionGroupName - 기능 그룹 이름</li>
|
||||
* <li>그 외는 기능 그룹 아이디</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param fetchSize 한 번에 가져올 기능 그룹수
|
||||
* @return 기능 그룹 목록
|
||||
*/
|
||||
public List<DataObject> getGroupList(ActionQuery req) {
|
||||
switch (ifEmpty(req.getBy(), () -> "")) {
|
||||
case "groupID": req.setBy("GRP_ID"); break;
|
||||
default : req.setBy("GRP_NM"); break;
|
||||
}
|
||||
req.setOrderBy(req.getBy());
|
||||
return actionGroupMapper.getGroupList(req);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹을 가져온다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 기능 그룹
|
||||
*/
|
||||
public List<ActionGroup> getGroups(String... groupIDs) {
|
||||
return actionGroupMapper.getGroups(groupIDs);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹을 가져온다.
|
||||
* @param groupID 기능 그룹 아이디
|
||||
* @return 기능 그룹
|
||||
*/
|
||||
public ActionGroup getGroup(String groupID) {
|
||||
return actionGroupMapper.getGroup(groupID);
|
||||
}
|
||||
|
||||
/**기능 그룹을 등록한다.
|
||||
* @param group 기능 그룹
|
||||
* @return 등록 여부
|
||||
* <ul><li>등록됐으면 true</li>
|
||||
* <li>그렇지 않으며 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean create(ActionGroup group) {
|
||||
if (group == null) return false;
|
||||
|
||||
ActionGroup existing = getGroup(group.getId());
|
||||
if (existing != null)
|
||||
throw applicationException(null)
|
||||
.setMessage(message("duplicate.object", "기능그룹"));
|
||||
|
||||
return actionGroupMapper.insertGroup(group) > 0;
|
||||
}
|
||||
|
||||
/**기능 그룹을 수정한다.
|
||||
* @param group 기능 그룹
|
||||
* @return 수정 여부
|
||||
* <ul><li>수정됐으면 true</li>
|
||||
* <li>그렇지 않으며 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean update(ActionGroup group) {
|
||||
if (group == null) return false;
|
||||
|
||||
return actionGroupMapper.updateGroup(group) > 0;
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹을 제거한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int remove(String... groupIDs) {
|
||||
return actionGroupMapper.removeGroups(groupIDs);
|
||||
}
|
||||
|
||||
/**지정하는 그룹의 기능 목록을 조회한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 기능 목록
|
||||
*/
|
||||
public List<DataObject> getActionList(ActionQuery req) {
|
||||
return actionGroupMapper.getActionList(req);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹에 기능들을 추가한다.
|
||||
* @param groupID 그룹 아이디
|
||||
* @param actions 기능(URL)
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int addActions(String groupID, String... actions) {
|
||||
return actionGroupMapper.addActions(groupID, actions);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹의 기능을 제거한다.
|
||||
* @param groupID 기능 그룹 아이디
|
||||
* @param actions 기능
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int removeActions(String groupID, String... actions) {
|
||||
return actionGroupMapper.removeActions(new String[] {groupID}, actions);
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package cokr.xit.base.security.access.service.bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import cokr.xit.base.security.access.ActionGroup;
|
||||
import cokr.xit.base.security.access.dao.AuthorityMapper;
|
||||
import cokr.xit.base.security.access.service.ActionGroupService;
|
||||
import cokr.xit.base.security.access.service.ActionQuery;
|
||||
import cokr.xit.foundation.component.AbstractServiceBean;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**기능 그룹 서비스 인터페이스 구현체
|
||||
* @author mjkhan
|
||||
*/
|
||||
@Service("actionGroupService")
|
||||
public class ActionGroupServiceBean extends AbstractServiceBean implements ActionGroupService {
|
||||
@Resource(name="actionGroupBean")
|
||||
private ActionGroupBean actionGroupBean;
|
||||
@Resource(name="authorityMapper")
|
||||
private AuthorityMapper authorityMapper;
|
||||
|
||||
@Override
|
||||
public List<DataObject> getGroupList(ActionQuery req) {
|
||||
return actionGroupBean.getGroupList(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActionGroup> getGroups(String... groupIDs) {
|
||||
return actionGroupBean.getGroups(groupIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionGroup getGroup(String groupID) {
|
||||
return actionGroupBean.getGroup(groupID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean create(ActionGroup group) {
|
||||
if (group == null) return false;
|
||||
|
||||
return actionGroupBean.create(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(ActionGroup group) {
|
||||
return actionGroupBean.update(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int remove(String... groupIDs) {
|
||||
authorityMapper.removeActionGroups(groupIDs);
|
||||
return actionGroupBean.remove(groupIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataObject> getActionList(ActionQuery req) {
|
||||
return actionGroupBean.getActionList(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addActions(String groupID, String... actions) {
|
||||
return actionGroupBean.addActions(groupID, actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeActions(String groupID, String... actions) {
|
||||
return actionGroupBean.removeActions(groupID, actions);
|
||||
}
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
package cokr.xit.base.security.access.service.bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import cokr.xit.base.security.Authority;
|
||||
import cokr.xit.base.security.access.dao.AuthorityMapper;
|
||||
import cokr.xit.base.security.access.service.AuthorityQuery;
|
||||
import cokr.xit.foundation.AbstractComponent;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**권한 정보 관리 Bean
|
||||
* @author mjkhan
|
||||
*/
|
||||
@Component("authorityBean")
|
||||
public class AuthorityBean extends AbstractComponent {
|
||||
@Resource(name = "authorityMapper")
|
||||
private AuthorityMapper authorityMapper;
|
||||
|
||||
/**주어진 조건의 권한 목록을 조회한다.
|
||||
* @param req 조회 조건
|
||||
* @return 권한 목록
|
||||
*/
|
||||
public List<DataObject> getAuthorityList(AuthorityQuery req) {
|
||||
switch (ifEmpty(req.getBy(), () -> "")) {
|
||||
case "authID": req.setBy("AUTH_ID"); break;
|
||||
default: req.setBy("AUTH_NM"); break;
|
||||
}
|
||||
req.setOrderBy("AUTH_TYPE, " + req.getBy());
|
||||
return authorityMapper.getAuthorityList(req);
|
||||
}
|
||||
|
||||
/**지정하는 권한들을 가져온다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 권한 목록
|
||||
*/
|
||||
public List<Authority> getAuthorities(String... authIDs) {
|
||||
return authorityMapper.getAuthorities(authIDs);
|
||||
}
|
||||
|
||||
/**지정하는 권한을 가져온다.
|
||||
* @param authID 권한 아이디
|
||||
* @return 권한
|
||||
*/
|
||||
public Authority getAuthority(String authID) {
|
||||
return authorityMapper.getAuthority(authID);
|
||||
}
|
||||
|
||||
/**권한을 등록한다.
|
||||
* @param authority 권한
|
||||
* @return 등록 여부
|
||||
* <ul><li>등록됐으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean create(Authority authority) {
|
||||
if (authority == null) return false;
|
||||
|
||||
if (!getAuthorities(authority.getId()).isEmpty())
|
||||
throw new RuntimeException(message("duplicate.object", "권한"));
|
||||
|
||||
return authorityMapper.insertAuthority(authority) > 0;
|
||||
}
|
||||
|
||||
/**권한을 수정한다.
|
||||
* @param authority 권한
|
||||
* @return 수정 여부
|
||||
* <ul><li>수정됐으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean update(Authority authority) {
|
||||
if (authority == null)
|
||||
return false;
|
||||
Authority existing = getAuthority(authority.getId());
|
||||
if (existing == null)
|
||||
throw applicationException(null).setMessage("존재하지 않는 권한입니다.");
|
||||
if (existing.type().isBuiltIn())
|
||||
throw applicationException(null).setMessage("내장된 권한은 수정할 수 없습니다.");
|
||||
|
||||
return authorityMapper.updateAuthority(authority) > 0;
|
||||
}
|
||||
|
||||
/**지정하는 권한들을 삭제한다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int removeAuthorities(String... authIDs) {
|
||||
return authorityMapper.removeAuthorities(authIDs);
|
||||
}
|
||||
|
||||
/**지정하는 권한의 기능 그룹 목록을 조회한다.
|
||||
* @param req 조회 조건(authIDs - 권한 아이디)
|
||||
* @return 권한별 기능 그룹 목록
|
||||
*/
|
||||
public List<DataObject> getActionGroupList(AuthorityQuery req) {
|
||||
req.setOrderBy("AUTH_ID, GRP_ID");
|
||||
return authorityMapper.getActionGroupList(req);
|
||||
}
|
||||
|
||||
/**지정하는 권한에 기능 그룹들을 추가한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int addActionGroups(String authID, String... groupIDs) {
|
||||
return authorityMapper.addActionGroups(authID, groupIDs);
|
||||
}
|
||||
|
||||
/**지정하는 권한에서 기능 그룹들을 삭제한다.<br />
|
||||
* 기능 그룹을 지정하지 않으면 해당 권한의 모든 기능 그룹을 삭제한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int removeActionGroups(String authID, String... groupIDs) {
|
||||
return authorityMapper.removeActionGroups(authID, groupIDs);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹들을 삭제한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int removeActionGroups(String... groupIDs) {
|
||||
return authorityMapper.removeActionGroups(groupIDs);
|
||||
}
|
||||
|
||||
/**권한별 기능 그룹, 기능 목록을 가져온다.
|
||||
* @return 권한별 기능 그룹, 기능 목록
|
||||
*/
|
||||
public List<DataObject> getActionList() {
|
||||
return authorityMapper.getActionList();
|
||||
}
|
||||
|
||||
/**지정하는 권한의 사용자를 조회한다.
|
||||
* @param req 조회 조건
|
||||
* @return 사용자 목록
|
||||
*/
|
||||
public List<DataObject> getUserList(AuthorityQuery req) {
|
||||
return authorityMapper.getUserList(req.setOrderBy("AUTH_ID, USER_ID"));
|
||||
}
|
||||
|
||||
/**지정하는 사용자의 권한 목록을 조회한다.
|
||||
* @param userID 사용자 아이디
|
||||
* @return 권한 목록
|
||||
*/
|
||||
public List<String> getUserAuths(String userID) {
|
||||
return authorityMapper.getUserAuths(userID);
|
||||
}
|
||||
|
||||
/**지정하는 권한에 사용자를 추가한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int addUsers(String authID, String... userIDs) {
|
||||
return authorityMapper.addUsers(authID, userIDs);
|
||||
}
|
||||
|
||||
/**지정하는 권한에서 사용자를 제거한다.<br />
|
||||
* 사용자를 지정하지 않으면 해당 권한의 모든 사용자를 제거한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int removeUsers(String authID, String... userIDs) {
|
||||
return authorityMapper.removeUsers(authID, userIDs);
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package cokr.xit.base.security.access.service.bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import cokr.xit.base.security.Authority;
|
||||
import cokr.xit.base.security.access.service.AuthorityQuery;
|
||||
import cokr.xit.base.security.access.service.AuthorityService;
|
||||
import cokr.xit.foundation.component.AbstractServiceBean;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**권한 정보 서비스 인터페이스의 구현체
|
||||
* @author mjkhan
|
||||
*/
|
||||
@Service("authorityService")
|
||||
public class AuthorityServiceBean extends AbstractServiceBean implements AuthorityService {
|
||||
@Resource(name="authorityBean")
|
||||
private AuthorityBean authorityMapper;
|
||||
|
||||
@Override
|
||||
public List<DataObject> getAuthorityList(AuthorityQuery req) {
|
||||
return authorityMapper.getAuthorityList(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Authority> getAuthorities(String... authIDs) {
|
||||
return authorityMapper.getAuthorities(authIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authority getAuthority(String authID) {
|
||||
return authorityMapper.getAuthority(authID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean create(Authority authority) {
|
||||
return authorityMapper.create(authority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(Authority authority) {
|
||||
return authorityMapper.update(authority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeAuthorities(String... authIDs) {
|
||||
return authorityMapper.removeAuthorities(authIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataObject> getActionGroupList(AuthorityQuery req) {
|
||||
return authorityMapper.getActionGroupList(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addActionGroups(String authID, String... groupIDs) {
|
||||
return authorityMapper.addActionGroups(authID, groupIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeActionGroups(String authID, String... groupIDs) {
|
||||
return authorityMapper.removeActionGroups(authID, groupIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataObject> getUserList(AuthorityQuery req) {
|
||||
return authorityMapper.getUserList(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addUsers(String authID, String... userIDs) {
|
||||
return authorityMapper.addUsers(authID, userIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeUsers(String authID, String... userIDs) {
|
||||
return authorityMapper.removeUsers(authID, userIDs);
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
/**사용자 접근 정보 관리 서비스 구현부.
|
||||
*/
|
||||
package cokr.xit.base.security.access.service.bean;
|
@ -0,0 +1,3 @@
|
||||
/**사용자 접근 정보 관리 서비스 인터페이스.
|
||||
*/
|
||||
package cokr.xit.base.security.access.service;
|
@ -0,0 +1,206 @@
|
||||
package cokr.xit.base.security.access.web;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import cokr.xit.base.security.access.ActionGroup;
|
||||
import cokr.xit.base.security.access.service.ActionGroupService;
|
||||
import cokr.xit.base.security.access.service.ActionQuery;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
import cokr.xit.foundation.web.AbstractController;
|
||||
|
||||
/**기능 그룹 서비스 웹 컨트롤러.<br />
|
||||
* {웹 컨텍스트}/actionGroup/*로 접근할 수 있다.
|
||||
* @author mjkhan
|
||||
*/
|
||||
@RequestMapping(name="기능 그룹", value="/actionGroup")
|
||||
public class ActionGroupController extends AbstractController {
|
||||
@Resource(name="actionGroupService")
|
||||
private ActionGroupService actionGroupService;
|
||||
|
||||
/**기능 그룹 서비스를 반환한다.
|
||||
* @return 기능 그룹 서비스
|
||||
*/
|
||||
protected ActionGroupService actionGroupService() {
|
||||
return actionGroupService;
|
||||
}
|
||||
|
||||
/**기능 그룹 관리 메인 화면을 연다.<br />
|
||||
* 이 때 {@link #getActionGroupList(String, String, Integer) 기능 그룹 조회} 결과도 같이 보낸다.
|
||||
* @return "actionGroup/actionGroup-main"
|
||||
*/
|
||||
@RequestMapping(name="기능 그룹 메인", value="/main.do")
|
||||
public ModelAndView main() {
|
||||
ModelAndView mav = getActionGroupList(new ActionQuery().setPageNum(1));
|
||||
mav.setViewName("base/actionGroup/actionGroup-main");
|
||||
return mav.addObject("groupList", toJson(mav.getModel().get("groupList")));
|
||||
}
|
||||
|
||||
/**주어진 조건에 따라 기능 그룹 목록을 조회한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>groupName - 기능 그룹 이름</li>
|
||||
* <li>그 외는 기능 그룹 아이디</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @return jsonView
|
||||
* <pre><code> {
|
||||
* "groupList": 기능 그룹 목록,
|
||||
* "groupStart": 목록 시작 인덱스,
|
||||
* "groupFetch": 한 번에 가져오는 기능 그룹 정보수,
|
||||
* "groupTotal": 조회 결과 찾은 기능 그룹 전체 수
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="기능 그룹 조회", value="/list.do")
|
||||
public ModelAndView getActionGroupList(ActionQuery req) {
|
||||
setFetchSize(req);
|
||||
return setCollectionInfo(
|
||||
new ModelAndView("jsonView"),
|
||||
actionGroupService.getGroupList(req),
|
||||
"group"
|
||||
);
|
||||
}
|
||||
|
||||
/**사용자의 기능 그룹 선택을 위한 화면을 연다.
|
||||
* @return "actionGroup/select"
|
||||
*/
|
||||
@RequestMapping(name="기능 그룹 선택", value="/select.do")
|
||||
public ModelAndView select(boolean multiple) {
|
||||
ModelAndView mav = getActionGroupList(new ActionQuery().setPageNum(1));
|
||||
mav.setViewName("base/actionGroup/select-actionGroup");
|
||||
List<DataObject> list = (List<DataObject>)mav.getModel().remove("groupList");
|
||||
mav.addObject("groupList", toJson(list.stream().filter(info -> !info.bool("builtIn")).collect(Collectors.toList())));
|
||||
return mav;
|
||||
}
|
||||
|
||||
/**지정한 기능 그룹 아이디 중복된 것인지 확인한다.
|
||||
* @param groupID 기능 그룹 아이디
|
||||
* @return jsonView
|
||||
* <pre><code> {
|
||||
* "duplicate": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="중복 확인", value="/duplicate.do")
|
||||
public ModelAndView isDuplicate(String groupID) {
|
||||
ActionGroup group = actionGroupService.getGroup(groupID);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("duplicate", group != null);
|
||||
}
|
||||
|
||||
@RequestMapping(name="기능 그룹 정보 조회", value="/info.do")
|
||||
public ModelAndView getInfo(String groupID) {
|
||||
if (!isEmpty(groupID)) {
|
||||
ActionQuery req = new ActionQuery()
|
||||
.setBy("groupID")
|
||||
.setTerm(groupID);
|
||||
List<DataObject> groupList = actionGroupService.getGroupList(req);
|
||||
DataObject groupInfo = !groupList.isEmpty() ? groupList.get(0) : null;
|
||||
boolean json = jsonResponse();
|
||||
return new ModelAndView(json ? "jsonView" : "base/actionGroup/actionGroup-info")
|
||||
.addObject("groupInfo", json ? groupInfo : toJson(groupInfo));
|
||||
} else {
|
||||
return new ModelAndView("base/actionGroup/actionGroup-info");
|
||||
}
|
||||
}
|
||||
|
||||
/**기능 그룹을 등록한다.
|
||||
* @param group 기능 그룹
|
||||
* @return jsonView
|
||||
* <pre><code> {
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="기능 그룹 등록", value="/create.do")
|
||||
public ModelAndView create(ActionGroup group) {
|
||||
boolean saved = actionGroupService.create(group);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("saved", saved);
|
||||
}
|
||||
|
||||
/**기능 그룹을 수정한다.
|
||||
* @param group 기능 그룹
|
||||
* @return jsonView
|
||||
* <pre><code> {
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="기능 그룹 수정", value="/update.do")
|
||||
public ModelAndView update(ActionGroup group) {
|
||||
boolean saved = actionGroupService.update(group);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("saved", saved);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹을 제거한다.
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return jsonView
|
||||
* <pre><code> {
|
||||
* "affected": 저장된 정보수,
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="기능 그룹 삭제", value="/remove.do")
|
||||
public ModelAndView remove(String... groupIDs) {
|
||||
int affected = actionGroupService.remove(groupIDs);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("affected", affected)
|
||||
.addObject("saved", affected > 0);
|
||||
}
|
||||
|
||||
/**지정하는 그룹의 기능 목록을 조회한다.
|
||||
* @param groupID 기능 그룹 아이디
|
||||
* @return jsonView
|
||||
* <pre><code> {
|
||||
* "actionList": [...]
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="기능 그룹별 기능(URL) 조회", value="/action/list.do")
|
||||
public ModelAndView getActionList(ActionQuery req) {
|
||||
setFetchSize(req);
|
||||
return setCollectionInfo(
|
||||
new ModelAndView("jsonView"),
|
||||
actionGroupService.getActionList(req),
|
||||
"action"
|
||||
);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹에 기능들을 추가한다.
|
||||
* @param groupID 그룹 아이디
|
||||
* @param actions 기능(URL)
|
||||
* @return jsonView
|
||||
* <pre><code> {
|
||||
* "affected": 저장된 정보수,
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="기능 그룹별 기능(URL) 추가", value="/action/add.do")
|
||||
public ModelAndView addActions(String groupID, String... actions) {
|
||||
int affected = actionGroupService.addActions(groupID, actions);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("affected", affected)
|
||||
.addObject("saved", affected > 0);
|
||||
}
|
||||
|
||||
/**지정하는 기능 그룹의 기능을 제거한다.
|
||||
* @param groupID 기능 그룹 아이디
|
||||
* @param actions 기능
|
||||
* @return jsonView
|
||||
* <pre><code> {
|
||||
* "affected": 저장된 정보수,
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="기능 그룹별 기능(URL) 삭제", value="/action/remove.do")
|
||||
public ModelAndView removeActions(String groupID, String... actions) {
|
||||
int affected = actionGroupService.removeActions(groupID, actions);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("affected", affected)
|
||||
.addObject("saved", affected > 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,254 @@
|
||||
package cokr.xit.base.security.access.web;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import cokr.xit.base.security.Authority;
|
||||
import cokr.xit.base.security.access.service.AuthorityQuery;
|
||||
import cokr.xit.base.security.access.service.AuthorityService;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
import cokr.xit.foundation.web.AbstractController;
|
||||
|
||||
/**권한 정보 서비스 웹 컨트롤러.<br />
|
||||
* {웹 컨텍스트}/authority/*로 접근할 수 있다.
|
||||
* @author mjkhan
|
||||
*/
|
||||
@RequestMapping(name="권한", value="/authority")
|
||||
public class AuthorityController extends AbstractController {
|
||||
@Resource(name="authorityService")
|
||||
private AuthorityService authorityService;
|
||||
|
||||
/**권한 정보 서비스를 반환한다.
|
||||
* @return 권한 정보 서비스
|
||||
*/
|
||||
protected AuthorityService authorityService() {
|
||||
return authorityService;
|
||||
}
|
||||
|
||||
/**권한 관리 메인 화면을 연다.<br />
|
||||
* 이 때 권한 목록 정보를 같이 보낸다.
|
||||
* @return "authority/authority-main"
|
||||
*/
|
||||
@RequestMapping(name="권한 메인", value="/main.do")
|
||||
public ModelAndView main() {
|
||||
ModelAndView mav = getAuthorityList(new AuthorityQuery().setPageNum(1));
|
||||
mav.setViewName("base/authority/authority-main");
|
||||
return mav.addObject("authorityList", toJson(mav.getModel().remove("authorityList")));
|
||||
}
|
||||
|
||||
/**주어진 조건의 권한 목록을 조회한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>authID - 권한 아이디</li>
|
||||
* <li>그 외는 권한 이름</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "authorityList": 권한 목록,
|
||||
* "authorityStart": 권한 목록 시작 인덱스,
|
||||
* "authorityFetch": 한 번에 가져오는 권한 정보수,
|
||||
* "authorityTotal": 조회로 찾은 전체 권한수
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="권한 조회", value="/list.do")
|
||||
public ModelAndView getAuthorityList(AuthorityQuery req) {
|
||||
setFetchSize(req);
|
||||
return setCollectionInfo(
|
||||
new ModelAndView("jsonView"),
|
||||
authorityService.getAuthorityList(req),
|
||||
"authority"
|
||||
);
|
||||
}
|
||||
|
||||
/**지정한 권한 아이디가 중복된 것인지 확인한다.
|
||||
* @param authID 권한 아이디
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "duplicate": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="중복 확인", value="/duplicate.do")
|
||||
public ModelAndView isDuplicate(String authID) {
|
||||
Authority authority = authorityService.getAuthority(authID);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("duplicate", authority != null);
|
||||
}
|
||||
|
||||
@RequestMapping(name="권한 정보 조회", value="/info.do")
|
||||
public ModelAndView getInfo(String authID) {
|
||||
if (!isEmpty(authID)) {
|
||||
AuthorityQuery req = new AuthorityQuery()
|
||||
.setBy("authID")
|
||||
.setTerm(authID);
|
||||
List<DataObject> authList = authorityService.getAuthorityList(req);
|
||||
DataObject authInfo = !authList.isEmpty() ? authList.get(0) : null;
|
||||
boolean json = jsonResponse();
|
||||
return new ModelAndView(json ? "jsonView" : "base/authority/authority-info")
|
||||
.addObject("authorityInfo", json ? authInfo : toJson(authInfo));
|
||||
} else {
|
||||
return new ModelAndView("base/authority/authority-info");
|
||||
}
|
||||
}
|
||||
|
||||
/**권한을 등록한다.
|
||||
* @param authority 권한
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="권한 등록", value="/create.do")
|
||||
public ModelAndView create(Authority authority) {
|
||||
boolean saved = authorityService.create(authority);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("saved", saved);
|
||||
}
|
||||
|
||||
/**권한을 수정한다.
|
||||
* @param authority 권한
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="권한 수정", value="/update.do")
|
||||
public ModelAndView update(Authority authority) {
|
||||
boolean saved = authorityService.update(authority);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("saved", saved);
|
||||
}
|
||||
|
||||
/**지정하는 권한들을 삭제한다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "affected": 저장된 정보수,
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="권한 삭제", value="/remove.do")
|
||||
public ModelAndView remove(String... authIDs) {
|
||||
int affected = authorityService.removeAuthorities(authIDs);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("affected", affected)
|
||||
.addObject("saved", affected > 0);
|
||||
}
|
||||
|
||||
/**지정하는 권한의 기능 그룹 목록을 조회한다.
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param authIDs 권한 아이디
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "actionList": 기능 목록,
|
||||
* "actionStart": 기능 목록 시작 인덱스,
|
||||
* "actionFetch": 한 번에 가져오는 기능 정보수,
|
||||
* "actionTotal": 조회로 찾은 전체 기능수
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="권한별 기능 조회", value="/action/list.do")
|
||||
public ModelAndView getActionList(AuthorityQuery req) {
|
||||
setFetchSize(req);
|
||||
return setCollectionInfo(
|
||||
new ModelAndView("jsonView"),
|
||||
authorityService.getActionGroupList(req),
|
||||
"action"
|
||||
);
|
||||
}
|
||||
|
||||
/**지정하는 권한에 기능 그룹들을 추가한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "affected": 저장된 정보수,
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="권한별 기능 추가", value="/action/add.do")
|
||||
public ModelAndView addActions(String authID, String... groupIDs) {
|
||||
int affected = authorityService.addActionGroups(authID, groupIDs);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("affected", affected)
|
||||
.addObject("saved", affected > 0);
|
||||
}
|
||||
|
||||
/**지정하는 권한에서 기능 그룹들을 삭제한다.<br />
|
||||
* 기능 그룹을 지정하지 않으면 해당 권한의 모든 기능 그룹을 삭제한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param groupIDs 기능 그룹 아이디
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "affected": 저장된 정보수,
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="권한별 기능 삭제", value="/action/remove.do")
|
||||
public ModelAndView removeActions(String authID, String... groupIDs) {
|
||||
int affected = authorityService.removeActionGroups(authID, groupIDs);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("affected", affected)
|
||||
.addObject("saved", affected > 0);
|
||||
}
|
||||
|
||||
/**지정하는 권한의 사용자 목록을 조회한다.
|
||||
* @param pageNum 시작 페이지 번호
|
||||
* @param authIDs 권한 아이디
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "userList": 사용자 목록,
|
||||
* "userStart": 사용자 목록 시작 인덱스,
|
||||
* "userFetch": 한 번에 가져오는 사용자 정보수,
|
||||
* "userTotal": 조회로 찾은 전체 사용자수
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="권한별 사용자 조회", value="/user/list.do")
|
||||
public ModelAndView getUserList(AuthorityQuery req) {
|
||||
setFetchSize(req);
|
||||
return setCollectionInfo(
|
||||
new ModelAndView("jsonView"),
|
||||
authorityService.getUserList(req),
|
||||
"user"
|
||||
);
|
||||
}
|
||||
|
||||
/**지정하는 권한에 사용자를 추가한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "affected": 저장된 정보수,
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="권한별 사용자 추가", value="/user/add.do")
|
||||
public ModelAndView addUsers(String authID, String... userIDs) {
|
||||
int affected = authorityService.addUsers(authID, userIDs);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("affected", affected)
|
||||
.addObject("saved", affected > 0);
|
||||
}
|
||||
|
||||
/**지정하는 권한에서 사용자를 삭제한다.<br />
|
||||
* 사용자를 지정하지 않으면 해당 권한의 모든 사용자를 삭제한다.
|
||||
* @param authID 권한 아이디
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "affected": 저장된 정보수,
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="권한별 사용자 삭제", value="/user/remove.do")
|
||||
public ModelAndView removeUsers(String authID, String... userIDs) {
|
||||
int affected = authorityService.removeUsers(authID, userIDs);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("affected", affected)
|
||||
.addObject("saved", affected > 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
/**사용자 접근 관리 서비스 웹 컨트롤러
|
||||
*/
|
||||
package cokr.xit.base.security.access.web;
|
@ -0,0 +1,165 @@
|
||||
package cokr.xit.base.security.authentication;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import cokr.xit.foundation.Assert;
|
||||
|
||||
/**사용자 인증(로그인) 정책 정보
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class AuthenticationPolicy {
|
||||
private String
|
||||
userID,
|
||||
ipAddress,
|
||||
duplicateYN,
|
||||
limitYN,
|
||||
createdBy,
|
||||
modifiedBy;
|
||||
private Date
|
||||
createdAt,
|
||||
lastModified;
|
||||
|
||||
/**사용자 ID를 반환한다.
|
||||
* @return 사용자 ID
|
||||
*/
|
||||
public String getUserID() {
|
||||
return userID;
|
||||
}
|
||||
|
||||
/**사용자 ID를 설정한다.
|
||||
* @param userID 사용자 ID
|
||||
*/
|
||||
public void setUserID(String userID) {
|
||||
this.userID = userID;
|
||||
}
|
||||
|
||||
/**IP 주소를 반환한다.
|
||||
* @return IP 주소
|
||||
*/
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
/**IP 주소를 설정한다.
|
||||
* @param ipAddress IP 주소
|
||||
*/
|
||||
public void setIpAddress(String ipAddress) {
|
||||
this.ipAddress = ipAddress;
|
||||
}
|
||||
|
||||
/**중복접근 허용 여부를 반환한다.
|
||||
* @return 중복접근 허용 여부
|
||||
* <ul><li>Y - 중복접근 허용함</li>
|
||||
* <li>N - 중복접근 허용하지 않음</li>
|
||||
* </ul>
|
||||
*/
|
||||
public String getDuplicateYN() {
|
||||
return Assert.ifEmpty(duplicateYN, "N");
|
||||
}
|
||||
|
||||
/**중복접근 허용 여부를 반환한다.
|
||||
* @return 중복접근 허용 여부
|
||||
* <ul><li>true - 중복접근 허용함</li>
|
||||
* <li>false - 중복접근 허용하지 않음</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean allowsDuplicateAccess() {
|
||||
return "Y".equals(getDuplicateYN());
|
||||
}
|
||||
|
||||
/**중복접근 허용 여부를 설정한다.
|
||||
* @param duplicateYN 중복접근 허용 여부
|
||||
* <ul><li>Y - 중복접근 허용함</li>
|
||||
* <li>N - 중복접근 허용하지 않음</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void setDuplicateYN(String duplicateYN) {
|
||||
this.duplicateYN = duplicateYN;
|
||||
}
|
||||
|
||||
/**접근제한 여부를 반환한다.
|
||||
* @return 접근제한 여부
|
||||
* <ul><li>Y - 접근 제한함</li>
|
||||
* <li>N - 접근 제한하지 않음</li>
|
||||
* </ul>
|
||||
*/
|
||||
public String getLimitYN() {
|
||||
return Assert.ifEmpty(limitYN, "N");
|
||||
}
|
||||
|
||||
/**접근제한 여부를 반환한다.
|
||||
* @return
|
||||
* <ul><li>true - 접근 제한함</li>
|
||||
* <li>false - 접근 제한하지 않음</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean limits() {
|
||||
return "Y".equals(getLimitYN());
|
||||
}
|
||||
|
||||
/**접근제한 여부를 설정한다.
|
||||
* @param limitYN 접근제한 여부
|
||||
* <ul><li>Y - 접근 제한함</li>
|
||||
* <li>N - 접근 제한하지 않음</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void setLimitYN(String limitYN) {
|
||||
this.limitYN = limitYN;
|
||||
}
|
||||
|
||||
/**등록자 ID를 반환한다.
|
||||
* @return 등록자 ID
|
||||
*/
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
/**등록자 ID를 설정한다.
|
||||
* @param createdBy 등록자 ID
|
||||
*/
|
||||
public void setCreatedBy(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
/**수정자 ID를 반환한다.
|
||||
* @return 수정자 ID
|
||||
*/
|
||||
public String getModifiedBy() {
|
||||
return modifiedBy;
|
||||
}
|
||||
|
||||
/**수정자 ID를 설정한다.
|
||||
* @param modifiedBy 수정자 ID
|
||||
*/
|
||||
public void setModifiedBy(String modifiedBy) {
|
||||
this.modifiedBy = modifiedBy;
|
||||
}
|
||||
|
||||
/**등록 일시를 반환한다.
|
||||
* @return 등록 일시
|
||||
*/
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
/**등록 일시를 설정한다.
|
||||
* @param createdAt 등록 일시
|
||||
*/
|
||||
public void setCreatedAt(Date createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
/**변경 일시를 반환한다.
|
||||
* @return 변경 일시
|
||||
*/
|
||||
public Date getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
/**변경 일시를 설정한다.
|
||||
* @param lastModified 변경 일시
|
||||
*/
|
||||
public void setLastModified(Date lastModified) {
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
package cokr.xit.base.security.authentication.dao;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import cokr.xit.base.security.authentication.AuthenticationPolicy;
|
||||
import cokr.xit.foundation.User;
|
||||
import cokr.xit.foundation.component.AbstractDao;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**사용자 인증 정보 DAO
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class AuthenticationDao extends AbstractDao {
|
||||
/**새 AuthenticationDao를 생성한다.
|
||||
*/
|
||||
public AuthenticationDao() {
|
||||
setNamespace("authentication");
|
||||
}
|
||||
|
||||
/**주어진 파라미터에 해당하는 사용자를 가져온다.
|
||||
* @param params 조회 조건 파라미터
|
||||
* @return 사용자
|
||||
*/
|
||||
public User getUser(Map<String, Object> params) {
|
||||
HashMap<String, Object> copy = new HashMap<>(params);
|
||||
if (isEmpty(copy.get("userIDs")))
|
||||
copy.put("userIDs", new Object[] {params.get("userID")});
|
||||
copy.put("password", true);
|
||||
List<User> users = selectList(
|
||||
sqlID("user.getUsers"),
|
||||
copy
|
||||
);
|
||||
return !users.isEmpty() ? users.get(0) : null;
|
||||
}
|
||||
|
||||
/**주어진 아이디의 사용자를 가져온다.
|
||||
* @param userID 사용자 아이디
|
||||
* @return 사용자
|
||||
*/
|
||||
public User getUser(String userID) {
|
||||
return getUser(
|
||||
params().set("userIDs", new String[] {userID})
|
||||
);
|
||||
}
|
||||
|
||||
/**인증 성공 시 실행되는 핸들러 메소드
|
||||
* @param authentication 인증 정보
|
||||
* @return 결과값
|
||||
*/
|
||||
public int onSuccess(Authentication authentication) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**인증 실패 시 실행되는 핸들러 메소드
|
||||
* @param params 인증 시 사용한 파라미터
|
||||
* @return 결과값
|
||||
*/
|
||||
public int onFailure(Map<String, String> params) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**로그 아웃 시 실행되는 핸들러 메소드
|
||||
* @param authentication 인증 정보
|
||||
* @return 결과값
|
||||
*/
|
||||
public int onLogout(Authentication authentication) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**주어진 조건의 사용자 인증 정책 목록을 반환한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>userName - 사용자 이름</li>
|
||||
* <li>그 이외는 사용자 아이디</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 페이지 이름
|
||||
* @param fetchSize 한 번에 가져올 인증 정책 갯수
|
||||
* @return 사용자 인증 정책 목록
|
||||
*/
|
||||
public List<DataObject> getPolicyList(String by, String term, int pageNum, int fetchSize) {
|
||||
switch (ifEmpty(by, () -> "")) {
|
||||
case "userName": by = "USER_NM"; break;
|
||||
default: by = "USER_ID"; break;
|
||||
}
|
||||
|
||||
DataObject params = params()
|
||||
.set("by", by)
|
||||
.set("term", ifEmpty(term, () -> null))
|
||||
.set("pageNum", pageNum)
|
||||
.set("fetchSize", fetchSize);
|
||||
return selectList(sqlID("getPolicyList"), params);
|
||||
}
|
||||
|
||||
/**지정한 사용자들의 인증 정책 목록을 가져온다.
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 인증 정책 목록
|
||||
*/
|
||||
public List<AuthenticationPolicy> getPolicies(String... userIDs) {
|
||||
DataObject params = params()
|
||||
.set("userIDs", ifEmpty(userIDs, () -> null))
|
||||
.set("pageNum", 1)
|
||||
.set("fetchSize", userIDs.length);
|
||||
return selectList(sqlID("getPolicies"), params);
|
||||
}
|
||||
|
||||
/**지정한 사용자의 인증 정책을 가져온다.
|
||||
* @param userID 사용자 아이디
|
||||
* @return 인증 정책
|
||||
*/
|
||||
public AuthenticationPolicy getPolicy(String userID) {
|
||||
List<AuthenticationPolicy> found = getPolicies(userID);
|
||||
return !found.isEmpty() ? found.get(0) : null;
|
||||
}
|
||||
|
||||
/**인증 정책을 등록한다.
|
||||
* @param policy 인증 정책
|
||||
* @return 등록 여부
|
||||
* <ul><li>등록 되었으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean create(AuthenticationPolicy policy) {
|
||||
if (policy == null)
|
||||
return false;
|
||||
|
||||
AuthenticationPolicy found = getPolicy(policy.getUserID());
|
||||
if (found != null)
|
||||
throw applicationException(null);
|
||||
|
||||
DataObject params = params()
|
||||
.set("policy", policy)
|
||||
.set("currentUser", currentUser());
|
||||
return insert(sqlID("insertPolicy"), params) > 0;
|
||||
}
|
||||
|
||||
/**인증 정책을 수정한다.
|
||||
* @param policy 인증 정책
|
||||
* @return 수정 여부
|
||||
* <ul><li>수정 되었으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean update(AuthenticationPolicy policy) {
|
||||
if (policy == null)
|
||||
return false;
|
||||
|
||||
DataObject params = params()
|
||||
.set("policy", policy)
|
||||
.set("currentUser", currentUser());
|
||||
return insert(sqlID("updatePolicy"), params) > 0;
|
||||
}
|
||||
|
||||
/**지정한 사용자의 인증 정책을 제거한다.
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int removePolicies(String... userIDs) {
|
||||
if (isEmpty(userIDs)) return 0;
|
||||
|
||||
return delete(sqlID("removePolicy"), params().set("userIDs", userIDs));
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
/**사용자 인증 정보 테이블 접근 객체
|
||||
*/
|
||||
package cokr.xit.base.security.authentication.dao;
|
@ -0,0 +1,3 @@
|
||||
/**사용자 인증 모듈
|
||||
*/
|
||||
package cokr.xit.base.security.authentication;
|
@ -0,0 +1,87 @@
|
||||
package cokr.xit.base.security.authentication.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
||||
import cokr.xit.base.security.authentication.AuthenticationPolicy;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**사용자 인증 서비스를 제공한다.
|
||||
* <ul><li>사용자 로그인 및 로그아웃 관련 핸들러 메소드</li>
|
||||
* <li>{@link #getPolicyList(String, String, int, int) 사용자 인증 정책 조회}</li>
|
||||
* <li>{@link #create(AuthenticationPolicy) 사용자 인증 정책 등록}</li>
|
||||
* <li>{@link #update(AuthenticationPolicy) 사용자 인증 정책 수정}</li>
|
||||
* <li>{@link #removePolicies(String...) 사용자 인증 정책 제거}</li>
|
||||
* </ul>
|
||||
* @author mjkhan
|
||||
*/
|
||||
public interface AuthenticationService extends UserDetailsService {
|
||||
/**인증 성공 시 실행되는 핸들러 메소드
|
||||
* @param authentication 인증 정보
|
||||
*/
|
||||
void onSuccess(Authentication authentication);
|
||||
|
||||
/**인증 실패 시 실행되는 핸들러 메소드
|
||||
* @param params 인증 시 사용한 파라미터
|
||||
*/
|
||||
void onFailure(Map<String, String> params);
|
||||
|
||||
/**로그 아웃 시 실행되는 핸들러 메소드
|
||||
* @param authentication 인증 정보
|
||||
*/
|
||||
void onLogout(Authentication authentication);
|
||||
|
||||
/**주어진 조건의 사용자 인증 정책 목록을 반환한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>userName - 사용자 이름</li>
|
||||
* <li>그 이외는 사용자 아이디</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 페이지 이름
|
||||
* @param fetchSize 한 번에 가져올 인증 정책 갯수
|
||||
* @return 사용자 인증 정책 목록
|
||||
*/
|
||||
List<DataObject> getPolicyList(String by, String term, int pageNum, int fetchSize);
|
||||
|
||||
/**지정한 사용자들의 인증 정책 목록을 가져온다.
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 인증 정책 목록
|
||||
*/
|
||||
List<AuthenticationPolicy> getPolicies(String... userIDs);
|
||||
|
||||
/**지정한 사용자의 인증 정책을 가져온다.
|
||||
* @param userID 사용자 아이디
|
||||
* @return 인증 정책
|
||||
*/
|
||||
default AuthenticationPolicy getPolicy(String userID) {
|
||||
List<AuthenticationPolicy> list = getPolicies(userID);
|
||||
return !list.isEmpty() ? list.get(0) : null;
|
||||
}
|
||||
|
||||
/**인증 정책을 등록한다.
|
||||
* @param policy 인증 정책
|
||||
* @return 등록 여부
|
||||
* <ul><li>등록 되었으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
boolean create(AuthenticationPolicy policy);
|
||||
|
||||
/**인증 정책을 수정한다.
|
||||
* @param policy 인증 정책
|
||||
* @return 수정 여부
|
||||
* <ul><li>수정 되었으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
boolean update(AuthenticationPolicy policy);
|
||||
|
||||
/**지정한 사용자의 인증 정책을 제거한다.
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
int removePolicies(String... userIDs);
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
package cokr.xit.base.security.authentication.service.bean;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import cokr.xit.base.security.authentication.AuthenticationPolicy;
|
||||
import cokr.xit.base.user.dao.UserMapper;
|
||||
import cokr.xit.base.user.service.UserQuery;
|
||||
import cokr.xit.foundation.User;
|
||||
import cokr.xit.foundation.component.AbstractDao;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**사용자 인증 정보 DAO
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class AuthenticationBean extends AbstractDao {
|
||||
@Resource(name = "userMapper")
|
||||
private UserMapper userMapper;
|
||||
|
||||
/**주어진 파라미터에 해당하는 사용자를 가져온다.
|
||||
* @param params 조회 조건 파라미터
|
||||
* @return 사용자
|
||||
*/
|
||||
public User getUser(Map<String, Object> params) {
|
||||
UserQuery req = new UserQuery()
|
||||
.setUserIDs((String)params.get("userID"));
|
||||
req.setPassword(true);
|
||||
List<User> users = userMapper.getUsers(req);
|
||||
|
||||
return !users.isEmpty() ? users.get(0) : null;
|
||||
}
|
||||
|
||||
/**주어진 아이디의 사용자를 가져온다.
|
||||
* @param userID 사용자 아이디
|
||||
* @return 사용자
|
||||
*/
|
||||
public User getUser(String userID) {
|
||||
return getUser(
|
||||
params().set("userIDs", new String[] {userID})
|
||||
);
|
||||
}
|
||||
|
||||
/**인증 성공 시 실행되는 핸들러 메소드
|
||||
* @param authentication 인증 정보
|
||||
* @return 결과값
|
||||
*/
|
||||
public int onSuccess(Authentication authentication) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**인증 실패 시 실행되는 핸들러 메소드
|
||||
* @param params 인증 시 사용한 파라미터
|
||||
* @return 결과값
|
||||
*/
|
||||
public int onFailure(Map<String, String> params) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**로그 아웃 시 실행되는 핸들러 메소드
|
||||
* @param authentication 인증 정보
|
||||
* @return 결과값
|
||||
*/
|
||||
public int onLogout(Authentication authentication) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**주어진 조건의 사용자 인증 정책 목록을 반환한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>userName - 사용자 이름</li>
|
||||
* <li>그 이외는 사용자 아이디</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 페이지 이름
|
||||
* @param fetchSize 한 번에 가져올 인증 정책 갯수
|
||||
* @return 사용자 인증 정책 목록
|
||||
*/
|
||||
public List<DataObject> getPolicyList(String by, String term, int pageNum, int fetchSize) {
|
||||
switch (ifEmpty(by, () -> "")) {
|
||||
case "userName": by = "USER_NM"; break;
|
||||
default: by = "USER_ID"; break;
|
||||
}
|
||||
|
||||
DataObject params = params()
|
||||
.set("by", by)
|
||||
.set("term", ifEmpty(term, () -> null))
|
||||
.set("pageNum", pageNum)
|
||||
.set("fetchSize", fetchSize);
|
||||
return selectList(sqlID("getPolicyList"), params);
|
||||
}
|
||||
|
||||
/**지정한 사용자들의 인증 정책 목록을 가져온다.
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 인증 정책 목록
|
||||
*/
|
||||
public List<AuthenticationPolicy> getPolicies(String... userIDs) {
|
||||
DataObject params = params()
|
||||
.set("userIDs", ifEmpty(userIDs, () -> null))
|
||||
.set("pageNum", 1)
|
||||
.set("fetchSize", userIDs.length);
|
||||
return selectList(sqlID("getPolicies"), params);
|
||||
}
|
||||
|
||||
/**지정한 사용자의 인증 정책을 가져온다.
|
||||
* @param userID 사용자 아이디
|
||||
* @return 인증 정책
|
||||
*/
|
||||
public AuthenticationPolicy getPolicy(String userID) {
|
||||
List<AuthenticationPolicy> found = getPolicies(userID);
|
||||
return !found.isEmpty() ? found.get(0) : null;
|
||||
}
|
||||
|
||||
/**인증 정책을 등록한다.
|
||||
* @param policy 인증 정책
|
||||
* @return 등록 여부
|
||||
* <ul><li>등록 되었으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean create(AuthenticationPolicy policy) {
|
||||
if (policy == null)
|
||||
return false;
|
||||
|
||||
AuthenticationPolicy found = getPolicy(policy.getUserID());
|
||||
if (found != null)
|
||||
throw applicationException(null);
|
||||
|
||||
DataObject params = params()
|
||||
.set("policy", policy)
|
||||
.set("currentUser", currentUser());
|
||||
return insert(sqlID("insertPolicy"), params) > 0;
|
||||
}
|
||||
|
||||
/**인증 정책을 수정한다.
|
||||
* @param policy 인증 정책
|
||||
* @return 수정 여부
|
||||
* <ul><li>수정 되었으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean update(AuthenticationPolicy policy) {
|
||||
if (policy == null)
|
||||
return false;
|
||||
|
||||
DataObject params = params()
|
||||
.set("policy", policy)
|
||||
.set("currentUser", currentUser());
|
||||
return insert(sqlID("updatePolicy"), params) > 0;
|
||||
}
|
||||
|
||||
/**지정한 사용자의 인증 정책을 제거한다.
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return 저장된 정보수
|
||||
*/
|
||||
public int removePolicies(String... userIDs) {
|
||||
if (isEmpty(userIDs)) return 0;
|
||||
|
||||
return delete(sqlID("removePolicy"), params().set("userIDs", userIDs));
|
||||
}
|
||||
}
|
@ -0,0 +1,229 @@
|
||||
package cokr.xit.base.security.authentication.service.bean;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
import cokr.xit.base.security.Authority;
|
||||
import cokr.xit.base.security.SecuredUserInfo;
|
||||
import cokr.xit.base.security.access.AccessContext;
|
||||
import cokr.xit.base.security.access.dao.AuthorityMapper;
|
||||
import cokr.xit.base.security.authentication.AuthenticationPolicy;
|
||||
import cokr.xit.base.security.authentication.dao.AuthenticationDao;
|
||||
import cokr.xit.base.security.authentication.service.AuthenticationService;
|
||||
import cokr.xit.base.security.authentication.web.AuthenticationExtraDetails;
|
||||
import cokr.xit.foundation.Access;
|
||||
import cokr.xit.foundation.ApplicationContainer;
|
||||
import cokr.xit.foundation.Log;
|
||||
import cokr.xit.foundation.User;
|
||||
import cokr.xit.foundation.UserInfo;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**사용자 인증 서비스 인터페이스 구현체
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class AuthenticationServiceBean extends DaoAuthenticationProvider implements AuthenticationService {
|
||||
/** 애플리케이션 컨테이너 */
|
||||
@Resource(name="applicationContainer")
|
||||
protected ApplicationContainer applicationContainer;
|
||||
/** 사용자 인증 DAO */
|
||||
@Resource(name="authenticationDao")
|
||||
private AuthenticationDao authenticationDao;
|
||||
/** 접근 권한 정보 */
|
||||
@Resource(name="accessContext")
|
||||
protected AccessContext accessContext;
|
||||
/** 접근 권한 DAO */
|
||||
@Resource(name="authorityMapper")
|
||||
private AuthorityMapper authorityMapper;
|
||||
|
||||
/**새 AuthenticationServiceBean를 생성한다.
|
||||
*/
|
||||
public AuthenticationServiceBean() {
|
||||
super();
|
||||
setUserDetailsService(this);
|
||||
}
|
||||
|
||||
/**로그를 반환한다.
|
||||
* @return 로그
|
||||
*/
|
||||
protected Log log() {
|
||||
return Log.get(getClass());
|
||||
}
|
||||
|
||||
/**사용자 인증 DAO를 반환한다.
|
||||
* @return 사용자 인증 DAO
|
||||
*/
|
||||
protected AuthenticationDao authenticationDao() {
|
||||
return authenticationDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecuredUserInfo loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
User user = authenticationDao.getUser(username);
|
||||
if (user == null)
|
||||
new BadCredentialsException("Bad credentials");
|
||||
|
||||
SecuredUserInfo userInfo = new SecuredUserInfo();
|
||||
userInfo.setUser(user);
|
||||
setAuthorities(userInfo);
|
||||
loadDetails(userInfo);
|
||||
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
Object obj = authentication.getPrincipal();
|
||||
if (obj instanceof UserInfo)
|
||||
return authentication;
|
||||
|
||||
obj = authentication.getDetails();
|
||||
if (!(obj instanceof AuthenticationExtraDetails))
|
||||
return authentication;
|
||||
|
||||
AuthenticationExtraDetails extraDetails = (AuthenticationExtraDetails)obj;
|
||||
Map<String, Object> params = extraDetails.getParams();
|
||||
log().debug("Authentication details: {}", params);
|
||||
|
||||
SecuredUserInfo userInfo = loadUser(params);
|
||||
|
||||
boolean valid = validate(userInfo, params);
|
||||
if (valid)
|
||||
checkAgainstPolicy(extraDetails, userInfo);
|
||||
|
||||
Authentication result = createSuccessAuthentication(userInfo.getUsername(), authentication, userInfo);
|
||||
return new UsernamePasswordAuthenticationToken(userInfo, result.getCredentials(), result.getAuthorities());
|
||||
}
|
||||
|
||||
/**인증하려는 사용자의 인증 정책을 가져와 확인한다.
|
||||
* @param extraDetails 인증 추가 정보
|
||||
* @param user 사용자 정보
|
||||
*/
|
||||
protected void checkAgainstPolicy(AuthenticationExtraDetails extraDetails, UserInfo user) {
|
||||
AuthenticationPolicy policy = authenticationDao.getPolicy(user.getId());
|
||||
if (policy == null || !policy.limits()) return;
|
||||
|
||||
String clientAddress = Access.getClientAddress(extraDetails.getRemoteAddress(), applicationContainer.getHostAddress());
|
||||
if (!clientAddress.equals(policy.getIpAddress()))
|
||||
throw new AuthenticationServiceException(messages.getMessage("authenticationFailure.policyViolated"));
|
||||
}
|
||||
|
||||
/**사용자 정보를 가져온다.
|
||||
* @param params 사용자 조회 파라미터
|
||||
* @return 사용자 정보
|
||||
*/
|
||||
private SecuredUserInfo loadUser(Map<String, Object> params) {
|
||||
User user = authenticationDao.getUser(params);
|
||||
if (user == null)
|
||||
throw new BadCredentialsException("Bad credentials");
|
||||
|
||||
SecuredUserInfo userInfo = new SecuredUserInfo();
|
||||
userInfo.setUser(user);
|
||||
setAuthorities(userInfo);
|
||||
loadDetails(userInfo);
|
||||
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/**인증한 사용자의 권한정보를 설정한다.
|
||||
* @param userInfo 사용자 정보
|
||||
*/
|
||||
protected void setAuthorities(SecuredUserInfo userInfo) {
|
||||
List<String> authIDs = authorityMapper.getUserAuths(userInfo.getId());
|
||||
if (!authIDs.contains("ROLE_ADMIN")) {
|
||||
// authIDs.add("ROLE_USER");
|
||||
// authIDs.add("ROLE_ANONYMOUS");
|
||||
}
|
||||
userInfo.setAuthorities(getAuthorities(authIDs));
|
||||
}
|
||||
|
||||
/**사용자 정보에 추가 정보를 설정한다.
|
||||
* @param user 사용자 정보
|
||||
*/
|
||||
protected void loadDetails(UserInfo user) {}
|
||||
|
||||
/**지정한 아이디의 권한을 가져온다.
|
||||
* @param authIDs 권한 아이디
|
||||
* @return 권한 목록
|
||||
*/
|
||||
protected List<Authority> getAuthorities(List<String> authIDs) {
|
||||
if (accessContext == null)
|
||||
return Collections.emptyList();
|
||||
|
||||
return accessContext.getAuthorities(authIDs);
|
||||
}
|
||||
|
||||
/**사용자 비밀번호가 맞는지 확인한다.
|
||||
* @param userInfo 사용자 정보
|
||||
* @param params 인증 파라미터
|
||||
* @return 비밀번호 유효성 여부
|
||||
* <ul><li>비밀번호가 맞으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
protected boolean validate(UserInfo userInfo, Map<String, Object> params) {
|
||||
boolean valid = getPasswordEncoder().matches((String)params.get("password"), userInfo.getPassword());
|
||||
if (!valid)
|
||||
throw new BadCredentialsException("Bad credentials");
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Authentication authentication) {
|
||||
log().debug("{} authenticated.", authentication.getPrincipal());
|
||||
authenticationDao.onSuccess(authentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Map<String, String> params) {
|
||||
log().debug("Authentication failed: {}", params);
|
||||
authenticationDao.onFailure(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogout(Authentication authentication) {
|
||||
log().debug("{} logged out.", authentication.getPrincipal());
|
||||
authenticationDao.onLogout(authentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return authentication.equals(UsernamePasswordAuthenticationToken.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataObject> getPolicyList(String by, String term, int pageNum, int fetchSize) {
|
||||
return authenticationDao.getPolicyList(by, term, pageNum, fetchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AuthenticationPolicy> getPolicies(String... userIDs) {
|
||||
return authenticationDao.getPolicies(userIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean create(AuthenticationPolicy policy) {
|
||||
return authenticationDao.create(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(AuthenticationPolicy policy) {
|
||||
return authenticationDao.update(policy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removePolicies(String... userIDs) {
|
||||
return authenticationDao.removePolicies(userIDs);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package cokr.xit.base.security.authentication.service.bean;
|
||||
|
||||
import cokr.xit.foundation.util.CharsEncoder;
|
||||
|
||||
/**비밀번호 인코더
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class PasswordEncoder extends CharsEncoder implements org.springframework.security.crypto.password.PasswordEncoder {
|
||||
@Override
|
||||
public boolean matches(CharSequence rawChars, String encodedChars) {
|
||||
return super.matches(rawChars, encodedChars);
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
/**사용자 인증 서비스 구현부
|
||||
*/
|
||||
package cokr.xit.base.security.authentication.service.bean;
|
@ -0,0 +1,3 @@
|
||||
/**사용자 인증 서비스 인터페이스
|
||||
*/
|
||||
package cokr.xit.base.security.authentication.service;
|
@ -0,0 +1,44 @@
|
||||
package cokr.xit.base.security.authentication.web;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
|
||||
import cokr.xit.foundation.Assert;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**인증 요청 처리 시 사용할 추가 정보
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class AuthenticationExtraDetails extends WebAuthenticationDetails {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private DataObject params;
|
||||
|
||||
/**새 AuthenticationExtraDetails를 생성한다.
|
||||
* @param request 서블릿 요청
|
||||
*/
|
||||
public AuthenticationExtraDetails(HttpServletRequest request) {
|
||||
super(request);
|
||||
|
||||
Map<String, String[]> paramMap = request.getParameterMap();
|
||||
paramMap.forEach((paramName, paramValue) -> {
|
||||
if (Assert.isEmpty(paramValue)) return;
|
||||
|
||||
if (params == null)
|
||||
params = new DataObject();
|
||||
|
||||
params.put(paramName, paramValue[0]);
|
||||
});
|
||||
}
|
||||
|
||||
/**서블릿 요청의 파라미터들을 반환한다.
|
||||
* @return 서블릿 요청의 파라미터
|
||||
*/
|
||||
public Map<String, Object> getParams() {
|
||||
return Assert.ifEmpty(params, Collections::emptyMap);
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package cokr.xit.base.security.authentication.web;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
|
||||
/**인증 요청 처리 시 추가 정보를 제공한다.
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class AuthenticationExtraDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, AuthenticationExtraDetails> {
|
||||
@Override
|
||||
public AuthenticationExtraDetails buildDetails(HttpServletRequest context) {
|
||||
return new AuthenticationExtraDetails(context);
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package cokr.xit.base.security.authentication.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.CredentialsExpiredException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import cokr.xit.base.security.authentication.service.AuthenticationService;
|
||||
import cokr.xit.foundation.Access;
|
||||
import cokr.xit.foundation.Assert;
|
||||
import cokr.xit.foundation.data.StringMap;
|
||||
|
||||
/**사용자 인증(로그인) 실패 핸들러
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class AuthenticationFailure extends SimpleUrlAuthenticationFailureHandler {
|
||||
@Resource(name="objectMapper")
|
||||
private ObjectMapper objectMapper;
|
||||
@Resource(name="authenticationService")
|
||||
private AuthenticationService authenticationService;
|
||||
@Resource(name="messageSource")
|
||||
private MessageSource messageSource;
|
||||
|
||||
/**사용자 인증 서비스 인터페이스를 반환한다.
|
||||
* @return 사용자 인증 서비스 인터페이스
|
||||
*/
|
||||
protected AuthenticationService authenticationService() {
|
||||
return authenticationService;
|
||||
}
|
||||
|
||||
private String failureMessage(String code) {
|
||||
return messageSource.getMessage("authenticationFailure." + code, null, Access.current().getLocale());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest hreq, HttpServletResponse hresp, AuthenticationException exception) throws IOException, ServletException {
|
||||
String reason = "authenticationFailed";
|
||||
if (exception instanceof UsernameNotFoundException)
|
||||
reason = failureMessage("usernameNotFound");
|
||||
else if (exception instanceof BadCredentialsException)
|
||||
reason = failureMessage("badCredentials");
|
||||
else if (exception instanceof CredentialsExpiredException)
|
||||
reason = failureMessage("credentialsExpired");
|
||||
else
|
||||
reason = Assert.rootCause(exception).getMessage();
|
||||
|
||||
Map<String, String> params = hreq.getParameterMap().entrySet().stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, (entry) -> entry.getValue()[0]));
|
||||
authenticationService.onFailure(params);
|
||||
|
||||
StringMap<Object> result = new StringMap<>().set("authenticated", false);
|
||||
setContentType(hresp, "application/json");
|
||||
print(hresp, objectMapper.writeValueAsString(result.set("reason", reason)));
|
||||
}
|
||||
|
||||
private void setContentType(HttpServletResponse hresp, String contentType) {
|
||||
hresp.setContentType(contentType);
|
||||
hresp.setCharacterEncoding("utf-8");
|
||||
}
|
||||
|
||||
private void print(HttpServletResponse hresp, String data) throws IOException {
|
||||
try (PrintWriter out = hresp.getWriter()) {
|
||||
out.print(data);
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
package cokr.xit.base.security.authentication.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import cokr.xit.base.security.authentication.service.AuthenticationService;
|
||||
import cokr.xit.foundation.UserInfo;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
|
||||
/**사용자 인증(로그인) 성공 핸들러
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class AuthenticationSuccess extends SavedRequestAwareAuthenticationSuccessHandler {
|
||||
@Resource(name="authenticationService")
|
||||
private AuthenticationService authenticationService;
|
||||
@Resource(name="objectMapper")
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
private boolean rememberUsername;
|
||||
|
||||
/**로그인 유지 여부를 설정한다.
|
||||
* @param remember 로그인 유지 여부
|
||||
* <ul><li>로그인을 유지하려면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void setRememberUsername(boolean remember) {
|
||||
this.rememberUsername = remember;
|
||||
}
|
||||
|
||||
/**사용자 인증 서비스 인터페이스를 반환한다.
|
||||
* @return 사용자 인증 서비스 인터페이스
|
||||
*/
|
||||
protected AuthenticationService authenticationService() {
|
||||
return authenticationService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest hreq, HttpServletResponse hresp, Authentication authentication) throws IOException, ServletException {
|
||||
DataObject result = onSuccess(hreq, hresp, authentication);
|
||||
setContentType(hresp, "application/json");
|
||||
print(hresp, objectMapper.writeValueAsString(result));
|
||||
}
|
||||
|
||||
/**사용자 인증 성공 핸들러<br />
|
||||
* 로그인 시간을 사용자 정보에 저장한다.
|
||||
* @param hreq 서블릿 요청
|
||||
* @param hresp 서블릿 응답
|
||||
* @param authentication 사용자 인증
|
||||
* @return 인증 정보
|
||||
* <pre>{@code {
|
||||
* "authenticated": true
|
||||
* }}</pre>
|
||||
*/
|
||||
protected DataObject onSuccess(HttpServletRequest hreq, HttpServletResponse hresp, Authentication authentication) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (principal instanceof UserInfo) {
|
||||
UserInfo user = (UserInfo)principal;
|
||||
user.setInfo("loggedInAt", new Date());
|
||||
remember(user, hreq, hresp);
|
||||
}
|
||||
authenticationService.onSuccess(authentication);
|
||||
|
||||
return new DataObject().set("authenticated", true);
|
||||
}
|
||||
|
||||
private void setContentType(HttpServletResponse hresp, String contentType) {
|
||||
hresp.setContentType(contentType);
|
||||
hresp.setCharacterEncoding("utf-8");
|
||||
}
|
||||
|
||||
private void remember(UserInfo user, HttpServletRequest hreq, HttpServletResponse hresp) {
|
||||
boolean remember = rememberUsername && "true".equals(hreq.getParameter("remember"));
|
||||
Cookie cookie = new Cookie("username", remember ? user.getUsername() : "");
|
||||
cookie.setMaxAge(remember ? Integer.MAX_VALUE : 0);
|
||||
hresp.addCookie(cookie);
|
||||
}
|
||||
|
||||
private void print(HttpServletResponse hresp, String data) throws IOException {
|
||||
try (PrintWriter out = hresp.getWriter()) {
|
||||
out.print(data);
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
package cokr.xit.base.security.authentication.web;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import cokr.xit.base.security.authentication.service.AuthenticationService;
|
||||
import cokr.xit.foundation.Assert;
|
||||
import cokr.xit.foundation.Log;
|
||||
|
||||
/**로그아웃 성공 핸들러
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class LogoutSuccess extends SimpleUrlLogoutSuccessHandler implements ApplicationContextAware, HttpSessionListener {
|
||||
private String successUrl;
|
||||
|
||||
/**로그아웃이 성공했을 때 redirect할 url을 반환한다.
|
||||
* @param contextPath 웹 애플리케이션 컨텍스트 경로
|
||||
* @return 로그아웃이 성공했을 때 redirect할 url
|
||||
* <ul><li>contextPath + successUrl</li>
|
||||
* <li>successUrl이 지정되어 있지 않으면 contextPath</li>
|
||||
* </ul>
|
||||
*/
|
||||
public String getSuccessUrl(String contextPath) {
|
||||
String path = Assert.ifEmpty(successUrl, "/");
|
||||
if (!path.startsWith("/"))
|
||||
path= "/" + path;
|
||||
return contextPath + path;
|
||||
}
|
||||
|
||||
/**로그아웃이 성공했을 때 redirect할 url을 설정한다.
|
||||
* @param successUrl 로그아웃이 성공했을 때 redirect할 url
|
||||
*/
|
||||
public void setSuccessUrl(String successUrl) {
|
||||
this.successUrl = successUrl;
|
||||
}
|
||||
|
||||
@Resource(name="authenticationService")
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**사용자 인증 서비스 인터페이스를 반환한다.
|
||||
* @return 사용자 인증 서비스 인터페이스
|
||||
*/
|
||||
protected AuthenticationService authenticationService() {
|
||||
return authenticationService;
|
||||
}
|
||||
|
||||
/**LogoutSuccess.class와 연계된 로그 객체를 반환한다.
|
||||
* @return 로그 객체
|
||||
*/
|
||||
protected Log log() {
|
||||
return Log.get(getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest hreq, HttpServletResponse hresp, Authentication authentication) throws IOException, ServletException {
|
||||
authenticationService.onLogout(authentication);
|
||||
HttpSession session = hreq.getSession(false);
|
||||
if (session != null)
|
||||
session.invalidate();
|
||||
removeCookies(hreq, hresp);
|
||||
hreq.logout();
|
||||
|
||||
hresp.setStatus(HttpServletResponse.SC_OK);
|
||||
hresp.sendRedirect(getSuccessUrl(hreq.getContextPath()));
|
||||
}
|
||||
|
||||
/**쿠키에 저장된 값들을 삭제한다.
|
||||
* @param hreq 서블릿 요청
|
||||
* @param hresp 서블릿 응답
|
||||
*/
|
||||
protected void removeCookies(HttpServletRequest hreq, HttpServletResponse hresp) {
|
||||
Cookie[] cookies = hreq.getCookies();
|
||||
if (cookies == null || cookies.length < 1) return;
|
||||
|
||||
for (Cookie cookie: cookies) {
|
||||
removeCookie(cookie, "JSESSIONID", "username");
|
||||
hresp.addCookie(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
/**지정하는 이름의 쿠키값을 삭제한다.
|
||||
* @param cookie 쿠키
|
||||
* @param cookieNames 쿠키값의 이름
|
||||
*/
|
||||
protected void removeCookie(Cookie cookie, String... cookieNames) {
|
||||
for (String name: cookieNames) {
|
||||
if (!name.equals(cookie.getName())) continue;
|
||||
|
||||
cookie.setMaxAge(0);
|
||||
cookie.setValue("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext actx) throws BeansException {
|
||||
if (!(actx instanceof WebApplicationContext)) return;
|
||||
|
||||
WebApplicationContext wactx = (WebApplicationContext)actx;
|
||||
wactx.getServletContext().addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionCreated(HttpSessionEvent evt) {}
|
||||
|
||||
@Override
|
||||
public void sessionDestroyed(HttpSessionEvent evt) {
|
||||
HttpSession session = evt.getSession();
|
||||
SecurityContext sctx = (SecurityContext)session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
if (sctx == null) return;
|
||||
|
||||
Authentication authentication = sctx.getAuthentication();
|
||||
log().debug("Session expired for {}", authentication.getPrincipal());
|
||||
authenticationService.onLogout(authentication);
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package cokr.xit.base.security.authentication.web;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import cokr.xit.base.security.authentication.AuthenticationPolicy;
|
||||
import cokr.xit.base.security.authentication.service.AuthenticationService;
|
||||
import cokr.xit.foundation.web.AbstractController;
|
||||
|
||||
/**인증 정책 컨트롤러<br />
|
||||
* {웹 컨텍스트}/authentication/policy/*로 접근할 수 있다.
|
||||
* @param <T> 인증 정책 유형
|
||||
* @author mjkhan
|
||||
*/
|
||||
@RequestMapping(name="인증 정책", value="/authentication/policy")
|
||||
public class PolicyController<T extends AuthenticationPolicy> extends AbstractController {
|
||||
@Resource(name="authenticationService")
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**사용자 인증 서비스를 반환한다.
|
||||
* @return 사용자 인증 서비스
|
||||
*/
|
||||
protected AuthenticationService authenticationService() {
|
||||
return authenticationService;
|
||||
}
|
||||
|
||||
/**주어진 조건의 사용자 인증 정책 목록을 반환한다.
|
||||
* @param by 조건 필드 이름
|
||||
* <ul><li>userName - 사용자 이름</li>
|
||||
* <li>그 이외는 사용자 아이디</li>
|
||||
* </ul>
|
||||
* @param term 조건 필드값
|
||||
* @param pageNum 페이지 이름
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "policyList": 정책 목록,
|
||||
* "policyStart": 정책 시작,
|
||||
* "policyFetch": 한 번에 가져온 정책수,
|
||||
* "policyTotal": 조회 결과 찾은 전체 정책수
|
||||
* }</code></pre>
|
||||
*/
|
||||
@RequestMapping(name="인증 정책 조회", value="/list.do")
|
||||
public ModelAndView getPolicies(String by, String term, @RequestParam(required=false, defaultValue="1") Integer pageNum) {
|
||||
int fetchSize = properties.getInt("pageSize");
|
||||
return setCollectionInfo(
|
||||
new ModelAndView("jsonView"),
|
||||
authenticationService.getPolicyList(by, term, pageNum, fetchSize),
|
||||
"policy"
|
||||
);
|
||||
}
|
||||
|
||||
/**인증 정책을 등록한다.
|
||||
* @param policy 인증 정책
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="인증 정책 등록", value="/created.do")
|
||||
public ModelAndView create(T policy) {
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("saved", authenticationService.create(policy));
|
||||
}
|
||||
|
||||
/**인증 정책을 수정한다.
|
||||
* @param policy 인증 정책
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="인증 정책 수정", value="/update.do")
|
||||
public ModelAndView update(T policy) {
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("saved", authenticationService.update(policy));
|
||||
}
|
||||
|
||||
/**지정한 사용자의 인증 정책을 제거한다.
|
||||
* @param userIDs 사용자 아이디
|
||||
* @return jsonView
|
||||
* <pre><code>{
|
||||
* "affected": 저장된 정보수,
|
||||
* "saved": true || false
|
||||
* }</code></pre>
|
||||
*/
|
||||
@PostMapping(name="인증 정책 제거", value="/remove.do")
|
||||
public ModelAndView remove(String... userIDs) {
|
||||
int affected = authenticationService.removePolicies(userIDs);
|
||||
return new ModelAndView("jsonView")
|
||||
.addObject("affected", affected)
|
||||
.addObject("saved", affected > 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
/**사용자 인증 웹 구현부
|
||||
*/
|
||||
package cokr.xit.base.security.authentication.web;
|
@ -0,0 +1,80 @@
|
||||
package cokr.xit.base.security.crypto;
|
||||
|
||||
import java.security.Key;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import cokr.xit.foundation.AbstractComponent;
|
||||
|
||||
public class Encryptor extends AbstractComponent {
|
||||
private String algorithm;
|
||||
private Key key;
|
||||
private IvParameterSpec iv;
|
||||
private Cipher cipher;
|
||||
|
||||
/**알고리즘을 반환한다.
|
||||
* @return 알고리즘
|
||||
*/
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
/**알고리즘을 설정한다.
|
||||
* @param algorithm 알고리즘
|
||||
* @return Encryptor
|
||||
*/
|
||||
public Encryptor setAlgorithm(String algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**SecretKey를 반환한다.
|
||||
* @return SecretKey
|
||||
*/
|
||||
public Key getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**SecretKey를 설정한다.
|
||||
* @param key SecretKey
|
||||
* @return Encryptor
|
||||
*/
|
||||
public Encryptor setKey(Key key) {
|
||||
this.key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**iv를 반환한다.
|
||||
* @return iv
|
||||
*/
|
||||
public IvParameterSpec getIv() {
|
||||
return iv;
|
||||
}
|
||||
|
||||
/**iv를 설정한다.
|
||||
* @param iv iv
|
||||
* @return Encryptor
|
||||
*/
|
||||
public Encryptor setIv(IvParameterSpec iv) {
|
||||
this.iv = iv;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String encrypt(String str) {
|
||||
if (isEmpty(str)) return "";
|
||||
|
||||
try {
|
||||
if (cipher == null) {
|
||||
cipher = Cipher.getInstance(algorithm);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
|
||||
}
|
||||
byte[] cipherText = cipher.doFinal(str.getBytes());
|
||||
return Base64.getEncoder()
|
||||
.encodeToString(cipherText);
|
||||
} catch (Exception e) {
|
||||
throw applicationException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package cokr.xit.base.security.crypto;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import cokr.xit.foundation.AbstractComponent;
|
||||
|
||||
public class KeyFactory extends AbstractComponent {
|
||||
private int keySize;
|
||||
private String algorithm;
|
||||
private KeyGenerator keyGen;
|
||||
|
||||
/**키 사이즈를 반환한다.
|
||||
* @return 키 사이즈
|
||||
*/
|
||||
public int getKeySize() {
|
||||
return Math.max(128, keySize);
|
||||
}
|
||||
|
||||
/**키 사이즈를 설정한다.
|
||||
* @param keySize 키 사이즈(128, 192, 또는 256 비트)
|
||||
* @return KeyFactory
|
||||
*/
|
||||
public KeyFactory setKeySize(int keySize) {
|
||||
if (!Arrays.asList(128, 192, 256).contains(keySize))
|
||||
throw new IllegalArgumentException("keySize must be either of 128, 192, 256");
|
||||
|
||||
this.keySize = keySize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**알고리즘을 반환한다.
|
||||
* @return 알고리즘
|
||||
*/
|
||||
public String getAlgorithm() {
|
||||
return ifEmpty(algorithm, "AES");
|
||||
}
|
||||
|
||||
/**알고리즘을 설정한다.
|
||||
* @param algorithm 알고리즘
|
||||
* @return KeyFactory
|
||||
*/
|
||||
public KeyFactory setAlgorithm(String algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static IvParameterSpec generateIv(int size) {
|
||||
byte[] iv = new byte[size];
|
||||
new SecureRandom().nextBytes(iv);
|
||||
return new IvParameterSpec(iv);
|
||||
}
|
||||
|
||||
public Key create() {
|
||||
try {
|
||||
if (keyGen == null) {
|
||||
keyGen = KeyGenerator.getInstance(getAlgorithm());
|
||||
keyGen.init(getKeySize());
|
||||
}
|
||||
return keyGen.generateKey();
|
||||
} catch (Exception e) {
|
||||
throw applicationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Key create(String str, String salt) {
|
||||
if (isEmpty(str) || isEmpty(salt)) return null;
|
||||
|
||||
try {
|
||||
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
|
||||
KeySpec spec = new PBEKeySpec(str.toCharArray(), salt.getBytes(), 65536, getKeySize());
|
||||
return new SecretKeySpec(skf.generateSecret(spec).getEncoded(), getAlgorithm());
|
||||
} catch (Exception e) {
|
||||
throw applicationException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
/**보안 정보 서비스 모듈.
|
||||
* <p>애플리케이션이 스프링 프레임워크의 보안 모듈(spring-security-*) 중
|
||||
* <ul><li>사용자 인증(authentication)</li>
|
||||
* <li>사용자 권한(authority)</li>
|
||||
* </ul>
|
||||
* 부분을 사용하는 것을 돕는다.
|
||||
* <p>보안 정보 서비스는 인증 정보와 권한 정보를 <a href="{@docRoot}/doc-files/xit-base-mysql.sql" target="_blank">데이터베이스 테이블</a>에 저장하여 관리한다.<br />
|
||||
* 보안 정보 테이블의 자세한 내용은 각 하위 모듈의 문서를 참고한다.
|
||||
* <ul><li>배포 모듈: xit-security-yy.mm.dd.jar</li>
|
||||
* <li>의존 모듈: {@link cokr.xit.foundation xit-foundation-yy.mm.dd.jar}</li>
|
||||
* </ul>
|
||||
*/
|
||||
package cokr.xit.base.security;
|
@ -0,0 +1,101 @@
|
||||
package cokr.xit.base.security.access.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import cokr.xit.base.security.access.ActionGroup;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
import cokr.xit.foundation.test.TestSupport;
|
||||
|
||||
public class ActionGroupServiceTest extends TestSupport {
|
||||
@Resource(name = "actionGroupService")
|
||||
private ActionGroupService actionGroupService;
|
||||
|
||||
@Test
|
||||
public void getGroupList() {
|
||||
ActionQuery req = new ActionQuery();
|
||||
actionGroupService.getGroupList(req);
|
||||
actionGroupService.getGroupList(req.setBy("groupID"));
|
||||
actionGroupService.getGroupList(req.setTerm("group-0"));
|
||||
actionGroupService.getGroupList(req.setBy(null).setTerm("group-zero"));
|
||||
|
||||
req.setBy(null).setTerm(null).setFetchSize(10);
|
||||
actionGroupService.getGroupList(req);
|
||||
actionGroupService.getGroupList(req.setBy("groupID"));
|
||||
actionGroupService.getGroupList(req.setTerm("group-0"));
|
||||
actionGroupService.getGroupList(req.setBy("groupID").setTerm("group-zero"));
|
||||
|
||||
actionGroupService.getGroups("group-0", "group-1", "group-2");
|
||||
actionGroupService.getGroups("group-0");
|
||||
}
|
||||
|
||||
private ActionGroup createGroup(String id) {
|
||||
ActionGroup group = new ActionGroup();
|
||||
group.setId(id);
|
||||
group.setName(id + " name");
|
||||
group.setDescription(id + " description");
|
||||
boolean created = actionGroupService.create(group);
|
||||
return created ? group : null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveGroup() {
|
||||
String groupID = "group-0";
|
||||
ActionGroup created = createGroup(groupID);
|
||||
Assertions.assertNotNull(created);
|
||||
|
||||
ActionGroup loaded = actionGroupService.getGroup(groupID);
|
||||
Assertions.assertNotNull(loaded);
|
||||
|
||||
Assertions.assertThrows(Exception.class, () -> actionGroupService.create(created));
|
||||
|
||||
created.setName("그룹 이름");
|
||||
Assertions.assertTrue(actionGroupService.update(created));
|
||||
|
||||
loaded = actionGroupService.getGroup(groupID);
|
||||
Assertions.assertEquals(created.getName(), loaded.getName());
|
||||
|
||||
deleteGroup(groupID);
|
||||
loaded = actionGroupService.getGroup(groupID);
|
||||
Assertions.assertNull(loaded);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveActions() {
|
||||
String groupID = "group-0";
|
||||
String[] actions = {"action-0", "action-1", "action-2"};
|
||||
ActionQuery req = new ActionQuery().setGroupIDs(groupID).setPageNum(1);
|
||||
|
||||
createGroup(groupID);
|
||||
|
||||
actionGroupService.addActions(groupID, actions);
|
||||
|
||||
List<DataObject> actionList = actionGroupService.getActionList(req);
|
||||
Assertions.assertEquals(actions.length, actionList.size());
|
||||
|
||||
actionGroupService.addActions(groupID, actions);
|
||||
actionList = actionGroupService.getActionList(req);
|
||||
Assertions.assertEquals(actions.length, actionList.size());
|
||||
|
||||
actions = new String[] {"action-0", "action-1", "action-2", "action-3"};
|
||||
actionGroupService.addActions(groupID, actions);
|
||||
actionList = actionGroupService.getActionList(req);
|
||||
Assertions.assertEquals(actions.length, actionList.size());
|
||||
|
||||
actionGroupService.removeActions(groupID, "action-2", "action-3");
|
||||
actionList = actionGroupService.getActionList(req);
|
||||
Assertions.assertEquals(2, actionList.size());
|
||||
|
||||
deleteGroup(groupID);
|
||||
actionList = actionGroupService.getActionList(req);
|
||||
Assertions.assertTrue(actionList.isEmpty());
|
||||
}
|
||||
|
||||
private void deleteGroup(String... groupIDs) {
|
||||
actionGroupService.remove(groupIDs);
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
package cokr.xit.base.security.access.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import cokr.xit.base.security.Authority;
|
||||
import cokr.xit.foundation.data.DataObject;
|
||||
import cokr.xit.foundation.test.TestSupport;
|
||||
|
||||
public class AuthorityServiceTest extends TestSupport {
|
||||
@Resource(name = "authorityService")
|
||||
private AuthorityService authorityService;
|
||||
|
||||
@Test
|
||||
public void getAuthorityList() {
|
||||
AuthorityQuery req = new AuthorityQuery();
|
||||
authorityService.getAuthorityList(req);
|
||||
authorityService.getAuthorityList(req.setBy("authID"));
|
||||
authorityService.getAuthorityList(req.setTerm("auth-0"));
|
||||
authorityService.getAuthorityList(req.setBy(null).setTerm("auth-zero"));
|
||||
authorityService.getAuthorityList(req.setBy(null).setTerm("auth-zero"));
|
||||
|
||||
req = new AuthorityQuery();
|
||||
authorityService.getAuthorityList(req.setPageNum(1).setFetchSize(10));
|
||||
authorityService.getAuthorityList(req.setBy("authID"));
|
||||
authorityService.getAuthorityList(req.setTerm("auth-0"));
|
||||
authorityService.getAuthorityList(req.setBy(null).setTerm("auth-zero"));
|
||||
|
||||
authorityService.getAuthorities("auth-0", "auth-1", "auth-2");
|
||||
authorityService.getAuthorities("auth-0");
|
||||
|
||||
Authority auth = authorityService.getAuthority("ROLE_ADMIN");
|
||||
Assertions.assertNotNull(auth);
|
||||
Assertions.assertEquals(Authority.Type.SUPER, auth.type());
|
||||
|
||||
auth = authorityService.getAuthority("ROLE_USER");
|
||||
Assertions.assertNotNull(auth);
|
||||
Assertions.assertEquals(Authority.Type.IMPLICIT, auth.type());
|
||||
|
||||
auth = authorityService.getAuthority("ROLE_ANONYMOUS");
|
||||
Assertions.assertNotNull(auth);
|
||||
Assertions.assertEquals(Authority.Type.IMPLICIT, auth.type());
|
||||
}
|
||||
|
||||
private Authority createAuthority(String id) {
|
||||
Authority authority = new Authority();
|
||||
authority.setId(id);
|
||||
authority.setName(id + " name");
|
||||
authority.setDescription(id + " description");
|
||||
boolean created = authorityService.create(authority);
|
||||
return created ? authority : null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveAuthority() {
|
||||
String authID = "auth-0";
|
||||
Authority created = createAuthority(authID);
|
||||
Assertions.assertNotNull(created);
|
||||
|
||||
Authority loaded = authorityService.getAuthority(authID);
|
||||
Assertions.assertNotNull(loaded);
|
||||
Assertions.assertEquals(Authority.Type.SYS_DEFINED, loaded.type());
|
||||
|
||||
created.setName("권한 이름");
|
||||
Assertions.assertTrue(authorityService.update(created));
|
||||
|
||||
loaded = authorityService.getAuthority(authID);
|
||||
Assertions.assertEquals(created.getName(), loaded.getName());
|
||||
|
||||
deleteAuthority(authID);
|
||||
loaded = authorityService.getAuthority(authID);
|
||||
Assertions.assertNull(loaded);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveActionGroups() {
|
||||
String authID = "auth-0";
|
||||
String[] groupIDs = {"group-0", "group-1", "group-2"};
|
||||
AuthorityQuery req = new AuthorityQuery().setAuthIDs(authID);
|
||||
|
||||
authorityService.addActionGroups(authID, groupIDs);
|
||||
List<DataObject> actionList = authorityService.getActionGroupList(req);
|
||||
Assertions.assertEquals(groupIDs.length, actionList.size());
|
||||
req.setPageNum(1).setFetchSize(10);
|
||||
actionList = authorityService.getActionGroupList(req);
|
||||
Assertions.assertEquals(groupIDs.length, actionList.size());
|
||||
|
||||
authorityService.addActionGroups(authID, groupIDs);
|
||||
actionList = authorityService.getActionGroupList(req.setPageNum(0).setFetchSize(0));
|
||||
Assertions.assertEquals(groupIDs.length, actionList.size());
|
||||
actionList = authorityService.getActionGroupList(req.setPageNum(1).setFetchSize(10));
|
||||
Assertions.assertEquals(groupIDs.length, actionList.size());
|
||||
|
||||
groupIDs = new String[] {"group-0", "group-1", "group-2", "group-3"};
|
||||
authorityService.addActionGroups(authID, groupIDs);
|
||||
actionList = authorityService.getActionGroupList(req.setPageNum(0).setFetchSize(0));
|
||||
Assertions.assertEquals(groupIDs.length, actionList.size());
|
||||
actionList = authorityService.getActionGroupList(req.setPageNum(1).setFetchSize(10));
|
||||
Assertions.assertEquals(groupIDs.length, actionList.size());
|
||||
|
||||
authorityService.removeActionGroups(authID, "group-2", "group-3");
|
||||
actionList = authorityService.getActionGroupList(req.setPageNum(0).setFetchSize(0));
|
||||
Assertions.assertEquals(2, actionList.size());
|
||||
actionList = authorityService.getActionGroupList(req.setPageNum(1).setFetchSize(10));
|
||||
Assertions.assertEquals(2, actionList.size());
|
||||
|
||||
deleteAuthority(authID);
|
||||
actionList = authorityService.getActionGroupList(req.setPageNum(0).setFetchSize(0));
|
||||
Assertions.assertTrue(actionList.isEmpty());
|
||||
actionList = authorityService.getActionGroupList(req.setPageNum(1).setFetchSize(10));
|
||||
Assertions.assertTrue(actionList.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveUsers() {
|
||||
String authID = "auth-0";
|
||||
String[] userIDs = {"user-0", "user-1", "user-2"};
|
||||
AuthorityQuery req = new AuthorityQuery().setAuthIDs(authID);
|
||||
|
||||
authorityService.addUsers(authID, userIDs);
|
||||
List<DataObject> userList = authorityService.getUserList(req);
|
||||
Assertions.assertEquals(userIDs.length, userList.size());
|
||||
userList = authorityService.getUserList(req.setPageNum(1).setFetchSize(10));
|
||||
Assertions.assertEquals(userIDs.length, userList.size());
|
||||
|
||||
authorityService.addUsers(authID, userIDs);
|
||||
userList = authorityService.getUserList(req.setPageNum(0).setFetchSize(0));
|
||||
Assertions.assertEquals(userIDs.length, userList.size());
|
||||
userList = authorityService.getUserList(req.setPageNum(1).setFetchSize(10));
|
||||
Assertions.assertEquals(userIDs.length, userList.size());
|
||||
|
||||
userIDs = new String[] {"user-0", "user-1", "user-2", "user-3"};
|
||||
authorityService.addUsers(authID, userIDs);
|
||||
userList = authorityService.getUserList(req.setPageNum(0).setFetchSize(0));
|
||||
Assertions.assertEquals(userIDs.length, userList.size());
|
||||
userList = authorityService.getUserList(req.setPageNum(1).setFetchSize(10));
|
||||
Assertions.assertEquals(userIDs.length, userList.size());
|
||||
|
||||
authorityService.removeUsers(authID, "user-2", "user-3");
|
||||
userList = authorityService.getUserList(req.setPageNum(0).setFetchSize(0));
|
||||
Assertions.assertEquals(2, userList.size());
|
||||
userList = authorityService.getUserList(req.setPageNum(1).setFetchSize(10));
|
||||
Assertions.assertEquals(2, userList.size());
|
||||
|
||||
deleteAuthority(authID);
|
||||
userList = authorityService.getUserList(req.setPageNum(0).setFetchSize(0));
|
||||
Assertions.assertTrue(userList.isEmpty());
|
||||
userList = authorityService.getUserList(req.setPageNum(1).setFetchSize(10));
|
||||
Assertions.assertTrue(userList.isEmpty());
|
||||
}
|
||||
|
||||
private void deleteAuthority(String... authIDs) {
|
||||
authorityService.removeAuthorities(authIDs);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package cokr.xit.base.security.authentication.service;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import cokr.xit.base.security.authentication.service.bean.PasswordEncoder;
|
||||
import cokr.xit.foundation.test.TestSupport;
|
||||
|
||||
public class AuthenticationServiceTest extends TestSupport {
|
||||
@Resource(name = "passwordEncoder")
|
||||
private PasswordEncoder passwordEncoder;
|
||||
@Resource(name = "authenticationService")
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
@Test
|
||||
void passwordEncoder() {
|
||||
String str = "5811807";
|
||||
String encoded = passwordEncoder.encode(str);
|
||||
System.out.println("encoded: " + encoded);
|
||||
Assertions.assertTrue(passwordEncoder.matches(str, encoded));
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadUserByUsername() {
|
||||
String userID = "test-user";
|
||||
create(userID);
|
||||
|
||||
UserDetails userDetails = authenticationService.loadUserByUsername(userID);
|
||||
Assertions.assertNotNull(userDetails);
|
||||
|
||||
deleteUsers(userID);
|
||||
}
|
||||
|
||||
protected boolean create(String userID) {
|
||||
String name = userID + " name";
|
||||
String password = userID + "-password";
|
||||
String insert = "INSERT INTO TBL_USER (\r\n"
|
||||
+ " USER_ID\r\n"
|
||||
+ " , USER_NM\r\n"
|
||||
+ " , PASSWD\r\n"
|
||||
+ " , LOCK_CNT\r\n"
|
||||
+ " , INS_DT\r\n"
|
||||
+ " , STATUS\r\n"
|
||||
+ ") VALUES (\r\n"
|
||||
+ " '" + userID + "'\r\n"
|
||||
+ " , '" + name + "'\r\n"
|
||||
+ " , '" + password + "'\r\n"
|
||||
+ " , 0\r\n"
|
||||
+ " , CURRENT_TIMESTAMP()\r\n"
|
||||
+ " , 'A'\r\n"
|
||||
+ ")";
|
||||
return testDao.execInsert(insert) == 1;
|
||||
}
|
||||
|
||||
protected void deleteUsers(String... userIDs) {
|
||||
String condition = Stream.of(userIDs)
|
||||
.map(userID -> "'" + userID + "'")
|
||||
.collect(Collectors.joining(","));
|
||||
|
||||
testDao.execDelete("DELETE FROM TBL_USER WHERE USER_ID IN (" + condition + ")");
|
||||
testDao.commit();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configuration>
|
||||
<Configuration>
|
||||
<Appenders>
|
||||
<Console name="console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d{HH:mm:ss,SSS} %5p [%c{1}] %m%n" />
|
||||
</Console>
|
||||
<RollingFile name="file" fileName="./logs/xit-base.log" filePattern="./logs/xit-base.%d{yy-MM-dd}.log" append="false">
|
||||
<PatternLayout pattern="%d{HH:mm:ss,SSS} %5p [%c{1}] %m%n"/>
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
|
||||
</Policies>
|
||||
</RollingFile>
|
||||
</Appenders>
|
||||
|
||||
<Loggers>
|
||||
<Logger name="org.springframework" level="INFO" additivity="false">
|
||||
<AppenderRef ref="console" />
|
||||
<AppenderRef ref="file" />
|
||||
</Logger>
|
||||
<Logger name="egovframework" level="INFO" additivity="false">
|
||||
<AppenderRef ref="console" />
|
||||
<AppenderRef ref="file" />
|
||||
</Logger>
|
||||
<Logger name="cokr.xit" level="DEBUG" additivity="false">
|
||||
<AppenderRef ref="console" />
|
||||
<AppenderRef ref="file" />
|
||||
</Logger>
|
||||
|
||||
<!-- log SQL with timing information, post execution -->
|
||||
<Logger name="jdbc.audit" level="OFF" />
|
||||
<Logger name="jdbc.sqlonly" level="OFF" />
|
||||
<Logger name="jdbc.resultset" level="OFF" />
|
||||
<Logger name="jdbc.resultsettable" level="OFF" />
|
||||
<Logger name="jdbc.sqltiming" level="DEBUG" additivity="false">
|
||||
<AppenderRef ref="console" />
|
||||
</Logger>
|
||||
|
||||
<Root level="DEBUG">
|
||||
<AppenderRef ref="console" />
|
||||
<AppenderRef ref="file" />
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
@ -0,0 +1,4 @@
|
||||
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
|
||||
|
||||
log4jdbc.dump.sql.maxlinelength=0
|
||||
log4jdbc.drivers=org.mariadb.jdbc.Driver
|
@ -0,0 +1,2 @@
|
||||
# see https://projectlombok.org/features/constructor lombok.copyableAnnotations
|
||||
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
|
@ -0,0 +1,5 @@
|
||||
authenticationFailure.usernameNotFound=\uc0ac\uc6a9\uc790\ub97c \ucc3e\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.
|
||||
authenticationFailure.badCredentials=\uc0ac\uc6a9\uc790 \uc544\uc774\ub514\ub098 \ube44\ubc00\ubc88\ud638\uac00 \uc798\ubabb\ub410\uc2b5\ub2c8\ub2e4.
|
||||
authenticationFailure.credentialsExpired=\ube44\ubc00\ubc88\ud638\uac00 \ub9cc\ub8cc\ub410\uc2b5\ub2c8\ub2e4.
|
||||
authenticationFailure.authenticationFailed=\uc0ac\uc6a9\uc790\ub97c \uc778\uc99d\ud558\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.
|
||||
authenticationFailure.policyViolated=\ub85c\uadf8\uc778 \uc815\ucc45\uc5d0 \ub530\ub77c \uc811\uadfc\uc774 \ucc28\ub2e8\ub410\uc2b5\ub2c8\ub2e4.
|
@ -0,0 +1,382 @@
|
||||
valueRequired={0}\uac00 \uc124\uc815\ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
pageNotFound=\uc694\uccad\ud558\uc2e0 \ud398\uc774\uc9c0\ub97c \ucc3e\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4.
|
||||
sessionExpired=\uc138\uc158\uc774 \ub9cc\ub8cc\ub410\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
duplicate.object=\uc774\ubbf8 \ub4f1\ub85d\ub41c {0}\uc785\ub2c8\ub2e4.
|
||||
|
||||
fail.common.msg=\uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4!
|
||||
fail.common.sql=sql \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4! error code: {0}, error msg: {1}
|
||||
info.nodata.msg=\ud574\ub2f9 \ub370\uc774\ud130\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#UI Common resource#
|
||||
table.num=\ubc88\ud638
|
||||
table.regdate=\ub4f1\ub85d\uc77c
|
||||
table.reger=\ub4f1\ub85d\uc790
|
||||
table.select=\uc120\ud0dd
|
||||
title.html=egovframe common component
|
||||
title.detail=\uc0c1\uc138\uc870\ud68c
|
||||
title.inquire=\uc870\ud68c
|
||||
title.update=\uc218\uc815
|
||||
title.create=\ub4f1\ub85d
|
||||
title.delete=\uc0ad\uc81c
|
||||
title.save=\uc800\uc7a5
|
||||
title.list=\ubaa9\ub85d
|
||||
title.searchCondition=\uac80\uc0c9\uc870\uac74
|
||||
title.search=\uac80\uc0c9\uc5b4
|
||||
title.reply=\ub2f5\uae00
|
||||
title.scrap=\uc2a4\ud06c\ub7a9
|
||||
title.comment=\ub313\uae00
|
||||
title.attachedFileSelect=\ud30c\uc77c\uc120\ud0dd
|
||||
title.attachedFileDelete=\ud30c\uc77c\uc0ad\uc81c
|
||||
title.link=\ub9c1\ud06c
|
||||
title.management=\uad00\ub9ac
|
||||
title.all=\uc804\uccb4
|
||||
|
||||
input.select=\uc120\ud0dd\ud558\uc138\uc694
|
||||
input.cSelect=\uc120\ud0dd
|
||||
input.input=\uc785\ub825
|
||||
input.button=\ubc84\ud2bc
|
||||
input.selectAll.title=\uc804\uccb4\uc120\ud0dd\uccb4\ud06c\ubc15\uc2a4
|
||||
input.yes=\uc608
|
||||
input.no=\uc544\ub2c8\uc624
|
||||
|
||||
select.searchCondition=\uc870\ud68c\uc870\uac74 \uc120\ud0dd
|
||||
|
||||
button.select=\uc120\ud0dd
|
||||
button.search=\uac80\uc0c9
|
||||
button.use=\uc0ac\uc6a9
|
||||
button.notUsed=\uc0ac\uc6a9\uc911\uc9c0
|
||||
button.inquire=\uc870\ud68c
|
||||
button.update=\uc218\uc815
|
||||
button.create=\ub4f1\ub85d
|
||||
button.delete=\uc0ad\uc81c
|
||||
button.deleteDatabase=\uc644\uc804\uc0ad\uc81c
|
||||
button.close=\ub2eb\uae30
|
||||
button.save=\uc800\uc7a5
|
||||
button.list=\ubaa9\ub85d
|
||||
button.reset=\ucde8\uc18c
|
||||
button.passwordUpdate=\uc554\ud638\ubcc0\uacbd
|
||||
button.subscribe=\uac00\uc785\uc2e0\uccad
|
||||
button.realname=\uc2e4\uba85\ud655\uc778
|
||||
button.moveToGpin=GPIN\uc2e4\uba85\ud655\uc778\uc73c\ub85c \uc774\ub3d9
|
||||
button.moveToIhidnum=\uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638 \uc2e4\uba85\ud655\uc778\uc73c\ub85c \uc774\ub3d9
|
||||
button.agree=\ub3d9\uc758
|
||||
button.disagree=\ube44\ub3d9\uc758
|
||||
button.possible=\uac00\ub2a5
|
||||
button.impossible=\ubd88\uac00\ub2a5
|
||||
button.qnaregist=Q&A\ub4f1\ub85d
|
||||
button.cnsltregist=\uc0c1\ub2f4\ub4f1\ub85d
|
||||
button.preview=\ubbf8\ub9ac\ubcf4\uae30
|
||||
button.next=\ub2e4\uc74c
|
||||
button.add=\ubc14\ub85c\ucd94\uac00
|
||||
button.confirm=\ud655\uc778
|
||||
button.back = \ub4a4\ub85c
|
||||
button.yes = \uc608
|
||||
button.no = \uc544\ub2c8\uc624
|
||||
button.home = \ud648
|
||||
button.user = \uc0ac\uc6a9\uc790\uc9c0\uc6d0
|
||||
button.cop = \ud611\uc5c5
|
||||
button.wrkstart = \ucd9c\uadfc
|
||||
button.wrkend = \ud1f4\uadfc
|
||||
button.reply = \ub2f5\uae00
|
||||
button.scrap = \uc2a4\ud06c\ub7a9
|
||||
button.comment = \ub313\uae00
|
||||
button.excel = \uc5d1\uc140
|
||||
button.init=\ucd08\uae30\ud654
|
||||
button.acknowledgment=\uc2b9\uc778
|
||||
button.cancelAcknowledgment=\uc2b9\uc778\ucde8\uc18c
|
||||
button.bulkUpload=\uc77c\uad04\ub4f1\ub85d
|
||||
button.log = \ub85c\uadf8
|
||||
button.set = \uc124\uc815
|
||||
button.move = \uc774\ub3d9
|
||||
|
||||
|
||||
#UI Common Message#
|
||||
common.noScriptTitle.msg=\uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c\ub294 \uc77c\ubd80 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc2e4 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
common.searchCondition.msg=\uc774 \ub808\uc774\uc544\uc6c3\uc740 \ud558\ub2e8 \uc815\ubcf4\ub97c \ub300\ud55c \uac80\uc0c9 \uc815\ubcf4\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
common.summary.list={0}\uc758 \ub0b4\uc5ed\uc5d0 \ub300\ud55c \ubaa9\ub85d\uc744 \ucd9c\ub825\ud569\ub2c8\ub2e4.
|
||||
common.summary.regist={0}\uc758 \ub4f1\ub85d \uac00\ub2a5\ud55c \ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc5ec \ub4f1\ub85d \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \ub4f1\ub85d\ud55c\ub2e4.
|
||||
common.summary.update={0}\uc758 \ub4f1\ub85d \uac00\ub2a5\ud55c \ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc5ec \ub4f1\ub85d \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \uc218\uc815\ud55c\ub2e4.
|
||||
common.summary.inqire={0}\uc758 \ub0b4\uc5ed\uc5d0 \ub300\ud55c \uc0c1\uc138\uc870\ud68c \ub0b4\uc5ed\uc744 \ucd9c\ub825\ud569\ub2c8\ub2e4.
|
||||
|
||||
common.save.msg=\uc800\uc7a5\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.regist.msg=\ub4f1\ub85d\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.delete.msg=\uc0ad\uc81c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.update.msg=\uc218\uc815\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.nodata.msg=\uc790\ub8cc\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. \ub2e4\ub978 \uac80\uc0c9\uc870\uac74\uc744 \uc120\ud0dd\ud574\uc8fc\uc138\uc694
|
||||
common.required.msg=(\uc740)\ub294 \ud544\uc218\uc785\ub825\ud56d\ubaa9\uc785\ub2c8\ub2e4.
|
||||
common.acknowledgement.msg=\uc2b9\uc778\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.acknowledgementcancel.msg=\uc2b9\uc778\ucde8\uc18c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.nocomment.msg=\ub313\uae00\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
common.noguest.msg=\uc791\uc131\ub41c \ubc29\uba85\ub85d\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
success.request.msg = \uc694\uccad\ucc98\ub9ac\uac00 \uc131\uacf5\uc801\uc73c\ub85c \uc218\ud589\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
success.common.select=\uc815\uc0c1\uc801\uc73c\ub85c \uc870\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
success.common.insert=\uc815\uc0c1\uc801\uc73c\ub85c \ub4f1\ub85d\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
success.common.update=\uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
success.common.delete=\uc815\uc0c1\uc801\uc73c\ub85c \uc0ad\uc81c\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
common.imposbl.fileupload = \ub354 \uc774\uc0c1 \ud30c\uc77c\uc744 \ucca8\ubd80\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
common.isConfmDe.msg=\uc2b9\uc778\uc77c\uc790\ub97c \ud655\uc778 \ubc14\ub78d\ub2c8\ub2e4.
|
||||
common.isExist.msg = \uc774\ubbf8 \uc874\uc7ac\ud558\uac70\ub098 \uacfc\uac70\uc5d0 \ub4f1\ub85d\uc774 \ub418\uc5c8\ub358 \uc0c1\ud0dc\uc785\ub2c8\ub2e4.
|
||||
|
||||
fail.common.insert = \uc0dd\uc131\uc774 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.update = \uc218\uc815\uc774 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.delete = \uc0ad\uc81c\uac00 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.delete.upperMenuExist = \ucc38\uc870\ub418\ub294 \uba54\ub274\uac00 \uc788\uc5b4 \uc0ad\uc81c\uac00 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.select = \uc870\ud68c\uc5d0 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.login = \ub85c\uadf8\uc778 \uc815\ubcf4\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.loginIncorrect = {0}\ud68c \uc774\uc0c1 \ub85c\uadf8\uc778 \uc811\uc18d\uc774 \uc2dc\ub3c4 \ub418\uc5b4 \uacc4\uc815\uc774 \uc7a0\uaca8\uc2b5\ub2c8\ub2e4!
|
||||
fail.common.login.password = \ud328\uc2a4\uc6cc\ub4dc \uc790\ub9ac \uc218\uac00 \uc77c\uce58 \ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.(8\uc790\ub9ac \uc774\uc0c1 20\uc790\ub9ac \uc774\ud558)
|
||||
fail.common.idsearch = \uc544\uc774\ub514\ub97c \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.pwsearch = \ube44\ubc00\ubc88\ud638\ub97c \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
fail.request.msg = \uc694\uccad\ucc98\ub9ac\ub97c \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.login.ip = \ub4f1\ub85d\ub41c IP\uac00 \uc544\ub2c8\ubbc0\ub85c \ub85c\uadf8\uc778\uc774 \uac70\ubd80\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#UI User Message#
|
||||
fail.user.passwordUpdate1=\ud604\uc7ac \ube44\ubc00\ubc88\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
fail.user.passwordUpdate2=\ube44\ubc00\ubc88\ud638\uc640 \ube44\ubc00\ubc88\ud638 \ud655\uc778\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
info.user.rlnmCnfirm=\uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc2e4\uba85\ud655\uc778\uc744 \ud558\uc2ed\uc2dc\uc624.
|
||||
success.user.rlnmCnfirm=\ud589\uc815\uc548\uc804\ubd80\uc758 \uc8fc\ubbfc\ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud569\ub2c8\ub2e4.
|
||||
fail.user.rlnmCnfirm=\ud589\uc815\uc548\uc804\ubd80\uc758 \uc8fc\ubbfc\ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
fail.user.connectFail=\uc2dc\uc2a4\ud15c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.(\uc778\uc99d\uc11c\ubc84 \uc5f0\uacb0 \uc2e4\ud328)
|
||||
info.user.rlnmPinCnfirm=\uacf5\uacf5 \uc544\uc774\ud540 \uc544\uc774\ub514\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc2e4\uba85\ud655\uc778\uc744 \ud558\uc2ed\uc2dc\uc624.
|
||||
success.user.rlnmPinCnfirm=\uacf5\uacf5\uc544\uc774\ud540\uc758 \ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud569\ub2c8\ub2e4.
|
||||
fail.user.rlnmPinCnfirm=\uacf5\uacf5\uc544\uc774\ud540\uc758 \ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
|
||||
#UI Cop Message#
|
||||
cop.extrlUser = \uc678\ubd80\uc0ac\uc6a9\uc790
|
||||
cop.intrlUser = \ub0b4\ubd80\uc0ac\uc6a9\uc790
|
||||
cop.private = \ube44\uacf5\uac1c
|
||||
cop.public = \uacf5\uac1c
|
||||
|
||||
cop.adbkNm = \uc8fc\uc18c\ub85d\uba85
|
||||
cop.othbcScope = \uacf5\uac1c\ubc94\uc704
|
||||
cop.company = \ud68c\uc0ac
|
||||
cop.part = \ubd80\uc11c
|
||||
cop.man = \uac1c\uc778
|
||||
cop.adbkUser = \uad6c\uc131\uc6d0
|
||||
cop.bbsNm = \uac8c\uc2dc\ud310\uba85
|
||||
cop.bbsIntrcn = \uac8c\uc2dc\ud310\uc18c\uac1c
|
||||
cop.bbsTyCode = \uac8c\uc2dc\ud310 \uc720\ud615
|
||||
cop.bbsAttrbCode = \uac8c\uc2dc\ud310 \uc18d\uc131
|
||||
cop.replyPosblAt = \ub2f5\uc7a5\uac00\ub2a5\uc5ec\ubd80
|
||||
cop.fileAtchPosblAt = \ud30c\uc77c\ucca8\ubd80\uac00\ub2a5\uc5ec\ubd80
|
||||
cop.posblAtchFileNumber = \ucca8\ubd80\uac00\ub2a5\ud30c\uc77c \uc22b\uc790
|
||||
cop.tmplatId = \ud15c\ud50c\ub9bf \uc815\ubcf4
|
||||
cop.guestList.subject = \ubc29\uba85\ub85d \uac8c\uc2dc\uae00\uc785\ub2c8\ub2e4.
|
||||
cop.nttSj = \uc81c\ubaa9
|
||||
cop.nttCn = \uae00\ub0b4\uc6a9
|
||||
cop.ntceBgnde = \uac8c\uc2dc\uc2dc\uc791\uc77c
|
||||
cop.ntceEndde = \uac8c\uc2dc\uc885\ub8cc\uc77c
|
||||
cop.ntcrNm = \uc791\uc131\uc790
|
||||
cop.password = \ud328\uc2a4\uc6cc\ub4dc
|
||||
cop.atchFile = \ud30c\uc77c\ucca8\ubd80
|
||||
cop.guestList = \ubc29\uba85\ub85d
|
||||
cop.guestListCn = \ubc29\uba85\ub85d \ub0b4\uc6a9
|
||||
cop.noticeTerm = \uac8c\uc2dc\uae30\uac04
|
||||
cop.atchFileList = \ucca8\ubd80\ud30c\uc77c\ubaa9\ub85d
|
||||
cop.cmmntyNm = \ucee4\ubba4\ub2c8\ud2f0\uba85
|
||||
cop.cmmntyIntrcn = \ucee4\ubba4\ub2c8\ud2f0 \uc18c\uac1c
|
||||
cop.cmmntyMngr = \ucee4\ubba4\ub2c8\ud2f0 \uad00\ub9ac\uc790
|
||||
cop.clbOprtr = \ub3d9\ud638\ud68c \uc6b4\uc601\uc790
|
||||
cop.clbIntrcn = \ub3d9\ud638\ud68c \uc18c\uac1c
|
||||
cop.clbNm = \ub3d9\ud638\ud68c \uba85
|
||||
cop.tmplatNm = \ud15c\ud50c\ub9bf\uba85
|
||||
cop.tmplatSeCode = \ud15c\ud50c\ub9bf \uad6c\ubd84
|
||||
cop.tmplatCours = \ud15c\ud50c\ub9bf\uacbd\ub85c
|
||||
cop.useAt = \uc0ac\uc6a9\uc5ec\ubd80
|
||||
cop.ncrdNm = \uc774\ub984
|
||||
cop.cmpnyNm = \ud68c\uc0ac\uba85
|
||||
cop.deptNm = \ubd80\uc11c\uba85
|
||||
cop.ofcpsNm = \uc9c1\uc704
|
||||
cop.clsfNm = \uc9c1\uae09
|
||||
cop.emailAdres = \uc774\uba54\uc77c\uc8fc\uc18c
|
||||
cop.telNo = \uc804\ud654\ubc88\ud638
|
||||
cop.mbtlNum = \ud734\ub300\ud3f0\ubc88\ud638
|
||||
cop.adres = \uc8fc\uc18c
|
||||
cop.extrlUserAt = \uc678\ubd80\uc0ac\uc6a9\uc790\uc5ec\ubd80
|
||||
cop.publicAt = \uacf5\uac1c\uc5ec\ubd80
|
||||
cop.remark = \ube44\uace0
|
||||
cop.trgetNm = \ucee4\ubba4\ub2c8\ud2f0/\ub3d9\ud638\ud68c \uc815\ubcf4
|
||||
cop.preview = \ubbf8\ub9ac\ubcf4\uae30
|
||||
|
||||
cop.withdraw.msg=\ud0c8\ud1f4\ucc98\ub9ac \ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.reregist.msg=\uc7ac\uac00\uc785 \ucc98\ub9ac\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.registmanager.msg=\uc6b4\uc601\uc9c4\uc73c\ub85c \ub4f1\ub85d\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.use.msg=\uc0ac\uc6a9 \ucc98\ub9ac\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.unuse.msg=\uc0ac\uc6a9\uc911\uc9c0 \ucc98\ub9ac\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.delete.confirm.msg=\uc0ac\uc6a9\uc911\uc9c0\ub97c \uc120\ud0dd\ud558\uc2e4 \uacbd\uc6b0 \ub2e4\uc2dc \uc0ac\uc6a9\uc73c\ub85c \ubcc0\uacbd\uc774 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4.
|
||||
cop.ing.msg=\uc2b9\uc778\uc694\uccad \uc911\uc785\ub2c8\ub2e4.
|
||||
cop.request.msg=\uac00\uc785\uc2e0\uccad\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc694\uccad\ub418\uc5c8\uc2b5\ub2c8\ub2e4
|
||||
cop.password.msg=\ud328\uc2a4\uc6cc\ub4dc\ub97c \uc785\ub825\ud574 \uc8fc\uc2ed\uc2dc\uc624.
|
||||
cop.password.not.same.msg=\ud328\uc2a4\uc6cc\ub4dc\uac00 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
cop.comment.wrterNm = \uc791\uc131\uc790
|
||||
cop.comment.commentCn = \ub0b4\uc6a9
|
||||
cop.comment.commentPassword = \ud328\uc2a4\uc6cc\ub4dc
|
||||
|
||||
cop.satisfaction.wrterNm = \uc791\uc131\uc790
|
||||
cop.satisfaction.stsfdgCn = \ub0b4\uc6a9
|
||||
cop.satisfaction.stsfdg = \ub9cc\uc871\ub3c4
|
||||
cop.satisfaction.stsfdgPassword = \ud328\uc2a4\uc6cc\ub4dc
|
||||
|
||||
cop.scrap.scrapNm = \uc2a4\ud06c\ub7a9\uba85
|
||||
|
||||
#UI USS Message#
|
||||
uss.ion.noi.ntfcSj=\uc81c\ubaa9
|
||||
uss.ion.noi.ntfcCn=\ub0b4\uc6a9
|
||||
uss.ion.noi.ntfcDate=\uc54c\ub9bc\uc77c\uc790
|
||||
uss.ion.noi.ntfcTime=\uc54c\ub9bc\uc2dc\uac04
|
||||
uss.ion.noi.ntfcHH=\uc54c\ub9bc\uc2dc\uac04
|
||||
uss.ion.noi.ntfcMM=\uc54c\ub9bc\ubd84
|
||||
uss.ion.noi.bhNtfcIntrvl=\uc0ac\uc804\uc54c\ub9bc\uac04\uaca9
|
||||
uss.ion.noi.bhNtfcIntrvl.msg=\uc0ac\uc804\uc54c\ub9bc\uac04\uaca9 \uc9c0\uc815\uc774 \ud544\uc694\ud569\ub2c8\ub2e4.
|
||||
uss.ion.noi.alertNtfcTime=\uc54c\ub9bc\uc77c\uc790 \ubc0f \uc2dc\uac04\uc774 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#UI COP Message#
|
||||
cop.sms.trnsmitTelno=\ubc1c\uc2e0\uc804\ud654\ubc88\ud638
|
||||
cop.sms.trnsmitCn=\uc804\uc1a1\ub0b4\uc6a9
|
||||
cop.sms.recptnTelno=\uc218\uc2e0\uc804\ud654\ubc88\ud638
|
||||
cop.sms.send=\uc804\uc1a1
|
||||
cop.sms.addRecptn=\ucd94\uac00
|
||||
cop.sms.recptnTelno.msg=\uc218\uc2e0\uc804\ud654\ubc88\ud638 \uc9c0\uc815\uc774 \ud544\uc694\ud569\ub2c8\ub2e4.
|
||||
|
||||
#UI sym.log Message#
|
||||
sym.log.histSeCode = \uc774\ub825\uad6c\ubd84
|
||||
sym.log.sysNm = \uc2dc\uc2a4\ud15c\uba85
|
||||
sym.log.histCn = \uc774\ub825\ub0b4\uc6a9
|
||||
sym.log.atchFile = \ucca8\ubd80\ud30c\uc77c
|
||||
sym.log.atchFileList = \ucca8\ubd80\ud30c\uc77c\ubaa9\ub85d
|
||||
sym.ems.receiver = \ubc1b\ub294\uc0ac\ub78c
|
||||
sym.ems.title = \uc81c\ubaa9
|
||||
sym.ems.content = \ubc1c\uc2e0\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors#
|
||||
errors.prefix=<div class="error">
|
||||
errors.suffix=</div><br/>
|
||||
|
||||
errors.required={0}\uc740(\ub294) \ud544\uc218 \uc785\ub825\uac12\uc785\ub2c8\ub2e4.
|
||||
errors.minlength={0}\uc740(\ub294) {1}\uc790 \uc774\uc0c1 \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.maxlength={0}\uc740(\ub294) {1}\uc790 \uc774\uc0c1 \uc785\ub825\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
errors.invalid={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uac12\uc785\ub2c8\ub2e4.
|
||||
errors.minInteger={0}\uc740(\ub294) \uc720\ud6a8\ud55c \uac12\uc774 \uc544\ub2d9\ub2c8\ub2e4. 1 \uc774\uc0c1\uc758 \uac12\uc744 \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.byte={0}\uc740(\ub294) byte\ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.short={0}\uc740(\ub294) short\ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.integer={0}\uc740(\ub294) \uc815\uc218 \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.long={0}\uc740(\ub294) long \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.float={0}\uc740(\ub294) \uc2e4\uc218 \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.double={0}\uc740(\ub294) double \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
|
||||
errors.date={0}\uc740(\ub294) \ub0a0\uc9dc \uc720\ud615\uc774 \uc544\ub2d9\ub2c8\ub2e4.
|
||||
errors.range={0}\uc740(\ub294) {1}\uacfc {2} \uc0ac\uc774\uc758 \uac12\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.creditcard={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc2e0\uc6a9\uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4.
|
||||
errors.email={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc774\uba54\uc77c \uc8fc\uc18c\uc785\ub2c8\ub2e4.
|
||||
|
||||
errors.ihidnum=\uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638\uc785\ub2c8\ub2e4.
|
||||
errors.korean={0}\uc740(\ub294) \ud55c\uae00\uc744 \uc785\ub825\ud558\uc154\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.ip=\uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 IP\uc8fc\uc18c\uc785\ub2c8\ub2e4.
|
||||
|
||||
errors.password1={0}\uc740(\ub294) 8~20\uc790 \ub0b4\uc5d0\uc11c \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.password2={0}\uc740(\ub294) \ud55c\uae00,\ud2b9\uc218\ubb38\uc790,\ub744\uc5b4\uc4f0\uae30\ub294 \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
errors.password3={0}\uc740(\ub294) \uc21c\ucc28\uc801\uc778 \uc22b\uc790\ub97c 4\uac1c\uc774\uc0c1 \uc5f0\uc18d\ud574\uc11c \uc0ac\uc6a9\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
errors.password4={0}\uc740(\ub294) \ubc18\ubcf5\ub418\ub294 \ubb38\uc790\ub098 \uc22b\uc790\ub97c 4\uac1c\uc774\uc0c1 \uc5f0\uc18d\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
errors.notKorean={0}\uc740(\ub294) \ud55c\uae00\uc744 \uc0ac\uc6a9\ud558\uc2e4\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
error.security.runtime.error = error
|
||||
|
||||
#Xss Errors#
|
||||
errors.xss.checkerUser=\ud574\ub2f9 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc0ac\uc6a9 \ubc0f \ucc98\ub9ac \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#File Upload / Download
|
||||
errors.file.extension=\uc9c0\uc6d0\ub418\ub294 \ud30c\uc77c\uc720\ud615\uc774 \uc544\ub2d9\ub2c8\ub2e4.
|
||||
errors.file.transfer=\ud30c\uc77c\uc804\uc1a1\uc911 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.
|
||||
success.file.transfer=\ud30c\uc77c\uc804\uc1a1\uc774 \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#Vlidator Errors- wordDicaryVO#
|
||||
wordDicaryVO.wordNm=\uc6a9\uc5b4\uba85
|
||||
wordDicaryVO.engNm=\uc601\ubb38\uba85
|
||||
wordDicaryVO.wordDc=\uc6a9\uc5b4\uc124\uba85
|
||||
wordDicaryVO.synonm=\ub3d9\uc758\uc5b4
|
||||
|
||||
#Vlidator Errors- cnsltManageVO#
|
||||
cnsltManageVO.cnsltSj=\uc0c1\ub2f4\uc81c\ubaa9
|
||||
cnsltManageVO.cnsltCn=\uc0c1\ub2f4\ub0b4\uc6a9
|
||||
cnsltManageVO.writngPassword=\uc791\uc131\ube44\ubc00\ubc88\ud638
|
||||
cnsltManageVO.areaNo=\uc9c0\uc5ed\ubc88\ud638
|
||||
cnsltManageVO.middleTelno=\uc911\uac04\uc804\ud654\ubc88\ud638
|
||||
cnsltManageVO.endTelno=\ub05d\uc804\ud654\ubc88\ud638
|
||||
cnsltManageVO.wrterNm=\uc791\uc131\uc790\uba85
|
||||
cnsltManageVO.managtCn=\ub2f5\ubcc0\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- siteManageVO#
|
||||
siteManageVO.siteNm=\uc0ac\uc774\ud2b8\uba85
|
||||
siteManageVO.siteUrl=\uc0ac\uc774\ud2b8 URL
|
||||
siteManageVO.siteDc=\uc0ac\uc774\ud2b8\uc124\uba85
|
||||
siteManageVO.siteThemaClCode=\uc0ac\uc774\ud2b8\uc8fc\uc81c\ubd84\ub958
|
||||
siteManageVO.actvtyAt=\ud65c\uc131\uc5ec\ubd80
|
||||
siteManageVO.useAt=\uc0ac\uc6a9\uc5ec\ubd80
|
||||
|
||||
#Vlidator Errors- recomendSiteManageVO#
|
||||
recomendSiteManageVO.recomendSiteNm=\ucd94\ucc9c\uc0ac\uc774\ud2b8\uba85
|
||||
recomendSiteManageVO.recomendSiteUrl=\ucd94\ucc9c\uc0ac\uc774\ud2b8 URL
|
||||
recomendSiteManageVO.recomendSiteDc=\ucd94\ucc9c\uc0ac\uc774\ud2b8\uc124\uba85
|
||||
recomendSiteManageVO.recomendResnCn=\ucd94\ucc9c\uc0ac\uc774\ud2b8\uc2b9\uc778\uc0ac\uc720
|
||||
recomendSiteManageVO.confmDe=\uc2b9\uc778\uc77c\uc790
|
||||
|
||||
#Vlidator Errors- hpcmManageVO#
|
||||
hpcmManageVO.hpcmSeCode=\ub3c4\uc6c0\ub9d0\uad6c\ubd84
|
||||
hpcmManageVO.hpcmDf=\ub3c4\uc6c0\ub9d0\uc815\uc758
|
||||
hpcmManageVO.hpcmDc=\ub3c4\uc6c0\ub9d0\uc124\uba85
|
||||
|
||||
#Vlidator Errors- newsManageVO#
|
||||
newsManageVO.newsSj=\ub274\uc2a4\uc81c\ubaa9
|
||||
newsManageVO.newsCn=\ub274\uc2a4\ub0b4\uc6a9
|
||||
newsManageVO.ntceDe=\uac8c\uc2dc\uc77c\uc790
|
||||
|
||||
#Vlidator Errors- faqManageVO#
|
||||
faqManageVO.qestnSj=\uc9c8\ubb38\uc81c\ubaa9
|
||||
faqManageVO.qestnCn=\uc9c8\ubb38\ub0b4\uc6a9
|
||||
faqManageVO.answerCn=\ub2f5\ubcc0\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- stplatManageVO#
|
||||
stplatManageVO.useStplatNm=\uc774\uc6a9\uc57d\uad00\uba85
|
||||
stplatManageVO.useStplatCn=\uc774\uc6a9\uc57d\uad00\ub0b4\uc6a9
|
||||
stplatManageVO.infoProvdAgreCn=\uc815\ubcf4\uc81c\uacf5\ub3d9\uc758\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- cpyrhtPrtcPolicyVO#
|
||||
cpyrhtPrtcPolicyVO.cpyrhtPrtcPolicyCn=\uc800\uc791\uad8c\ubcf4\ud638\uc815\ucc45\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- qnaManageVO#
|
||||
qnaManageVO.qestnSj=\uc9c8\ubb38\uc81c\ubaa9
|
||||
qnaManageVO.qestnCn=\uc9c8\ubb38\ub0b4\uc6a9
|
||||
qnaManageVO.writngPassword=\uc791\uc131\ube44\ubc00\ubc88\ud638
|
||||
qnaManageVO.areaNo=\uc9c0\uc5ed\ubc88\ud638
|
||||
qnaManageVO.middleTelno=\uc911\uac04\uc804\ud654\ubc88\ud638
|
||||
qnaManageVO.endTelno=\ub05d\uc804\ud654\ubc88\ud638
|
||||
qnaManageVO.wrterNm=\uc791\uc131\uc790\uba85
|
||||
qnaManageVO.answerCn=\ub2f5\ubcc0\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- ReprtStatsVO#
|
||||
sts.reprtId = \ubcf4\uace0\uc11cID
|
||||
sts.title = \ubcf4\uace0\uc11c\uba85
|
||||
sts.category = \ubcf4\uace0\uc11c\uc720\ud615
|
||||
sts.status = \uc9c4\ud589\uc0c1\ud0dc
|
||||
sts.regDate = \ub4f1\ub85d\uc77c\uc2dc
|
||||
|
||||
#Rest day messages#
|
||||
sym.cal.restDay = \ud734\uc77c\uc77c\uc790
|
||||
sym.cal.restName = \ud734\uc77c\uba85
|
||||
sym.cal.restDetail = \ud734\uc77c\uc124\uba85
|
||||
sym.cal.restCategory = \ud734\uc77c\uad6c\ubd84
|
||||
|
||||
image.errorBg = \uc624\ub958\uc774\ubbf8\uc9c0
|
||||
|
||||
|
||||
#Custom message#
|
||||
custom.fail.access=\uc815\uc0c1\uc801\uc778 \uc811\uadfc\uc774 \uc544\ub2d9\ub2c8\ub2e4. \ub85c\uadf8\uc778 \ud6c4 \uc774\uc6a9\ud558\uc138\uc694.
|
||||
custom.fail.accessDenied=\uc694\uccad\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
custom.isNotExist.msg=\ucc98\ub9ac\uc5d0 \ud544\uc694\ud55c \uc790\ub8cc\uac00 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
@ -0,0 +1,277 @@
|
||||
fail.common.msg=error ocurred!
|
||||
fail.common.sql=sql error ocurred! error code: {0}, error msg: {1}
|
||||
info.nodata.msg=no data found.
|
||||
|
||||
#UI Common resource#
|
||||
table.num=num.
|
||||
table.regdate=reg.date
|
||||
table.reger=registrant
|
||||
table.select=select
|
||||
title.html=egovframe common component
|
||||
title.detail=Detail Inquiry
|
||||
title.inquire=Inquire
|
||||
title.update=Modify
|
||||
title.create=Create
|
||||
title.delete=Delete
|
||||
title.save=Save
|
||||
title.list=List
|
||||
title.searchCondition=search condition
|
||||
title.search=keyword
|
||||
title.reply=reply
|
||||
title.scrap=scrap
|
||||
title.comment=comment
|
||||
title.attachedFileSelect=attached file
|
||||
title.attachedFileDelete=attached file delete
|
||||
title.link=link
|
||||
title.management=Management
|
||||
title.all=All
|
||||
|
||||
input.select=Select
|
||||
input.cSelect=Select
|
||||
input.input=input
|
||||
input.button=button
|
||||
input.selectAll.title=Checkbox select all
|
||||
input.yes=Yes
|
||||
input.no=No
|
||||
|
||||
select.searchCondition=select condition select
|
||||
|
||||
button.select=select
|
||||
button.search=Search
|
||||
button.use=use
|
||||
button.notUsed=Not used
|
||||
button.inquire=inquire
|
||||
button.update=update
|
||||
button.create=create
|
||||
button.delete=delete
|
||||
button.deleteDatabase=Wiping
|
||||
button.close=close
|
||||
button.save=save
|
||||
button.list=list
|
||||
button.reset=reset
|
||||
button.passwordUpdate=password update
|
||||
button.subscribe=subscribe
|
||||
button.realname=realname confirm
|
||||
button.moveToGpin=move to gpin confirm
|
||||
button.moveToIhidnum=move to ihidnum confirm
|
||||
button.agree=agree
|
||||
button.disagree=disagree
|
||||
button.possible=possible
|
||||
button.impossible=impossible
|
||||
button.qnaregist=Q&A create
|
||||
button.cnsltregist=Counsel create
|
||||
button.preview=preview
|
||||
button.next=nexut
|
||||
button.add=add it now
|
||||
button.confirm=confirm
|
||||
button.back =back
|
||||
button.yes =yes
|
||||
button.no =no
|
||||
button.home =home
|
||||
button.user =user support
|
||||
button.cop =cooperation
|
||||
button.wrkstart = work start
|
||||
button.wrkend = work end
|
||||
button.reply = reply
|
||||
button.scrap = scrap
|
||||
button.comment = comment
|
||||
button.excel = excel
|
||||
button.init=init
|
||||
button.acknowledgment=acknowledgment
|
||||
button.cancelAcknowledgment=cancel acknowledgment
|
||||
button.bulkUpload=bulk upload
|
||||
button.log = log
|
||||
button.set = set
|
||||
button.move = move
|
||||
|
||||
|
||||
#UI Common Message#
|
||||
common.noScriptTitle.msg=I can't use all functions in browser JavaScript is not supported.
|
||||
common.searchCondition.msg=This layout is a lower information searches made up of information.
|
||||
|
||||
common.summary.list={0} A list of the details of the output.
|
||||
common.summary.regist={0} Registered by typing the possible contents of registers by clicking the button.
|
||||
common.summary.update={0} Registered by typing the possible content of modification by clicking the button.
|
||||
common.summary.inqire={0} Full inquiry details about the details of the output.
|
||||
|
||||
common.save.msg=confirm save?
|
||||
common.regist.msg=confirm regist?
|
||||
common.delete.msg=confirm delete?
|
||||
common.update.msg=confirm update?
|
||||
common.nodata.msg=There is no data. please choose another seach keyword
|
||||
common.required.msg=is required field
|
||||
common.acknowledgement.msg=confirm acknowledgement?
|
||||
common.acknowledgementcancel.msg=confirm acknowledgement cancel?
|
||||
common.nocomment.msg=There is no comment.
|
||||
common.noguest.msg=There is no guest notice.
|
||||
|
||||
success.request.msg=you're request successfully done
|
||||
success.common.select=successfully selected
|
||||
success.common.insert=successfully inserted
|
||||
success.common.update=successfully updated
|
||||
success.common.delete=successfully deleted
|
||||
|
||||
common.imposbl.fileupload = cannot upload files
|
||||
common.isConfmDe.msg=Please check the approval date box
|
||||
common.isExist.msg = already exist
|
||||
|
||||
fail.common.insert = fail to insert.
|
||||
fail.common.update = fail to update
|
||||
fail.common.delete = fail to delete
|
||||
fail.common.delete.upperMenuExist = fail to delete[upperMenuId foreign key error]
|
||||
fail.common.select = fail to select
|
||||
fail.common.login = login information is not correct
|
||||
fail.common.loginIncorrect = login in more than {0} account will be locked!
|
||||
fail.common.login.password = password information is not correct(password digit should be 8 to 20)
|
||||
fail.common.idsearch = can not find id
|
||||
fail.common.pwsearch = can not find password
|
||||
fail.request.msg = Failed to handle the request
|
||||
fail.common.login.ip = Login is refused because it is not a registered IP.
|
||||
|
||||
|
||||
#UI User Message#
|
||||
fail.user.passwordUpdate1=current password is not correct
|
||||
fail.user.passwordUpdate2=password confirm is not correct
|
||||
info.user.rlnmCnfirm=realname confirm ready
|
||||
success.user.rlnmCnfirm=it is realname
|
||||
fail.user.rlnmCnfirm=it is not realname
|
||||
fail.user.connectFail=connection fail
|
||||
|
||||
#UI Cop Message#
|
||||
cop.extrlUser = External User
|
||||
cop.intrlUser = Internal User
|
||||
cop.private = private
|
||||
cop.public = public
|
||||
|
||||
cop.bbsNm = BBS Name
|
||||
cop.bbsIntrcn = BBS Introduction
|
||||
cop.bbsTyCode = BBS Type
|
||||
cop.bbsAttrbCode = BBS Attribute
|
||||
cop.replyPosblAt = Reply Possible Alternative
|
||||
cop.fileAtchPosblAt = File Attach Possible Alternative
|
||||
cop.posblAtchFileNumber = Possible Attach File Number
|
||||
cop.tmplatId = Template Information
|
||||
cop.guestList.subject = This article registered by Guest List
|
||||
cop.nttSj = Notice Subject
|
||||
cop.nttCn = Notice Contents
|
||||
cop.ntceBgnde = Notice Start Date
|
||||
cop.ntceEndde = Notice End Date
|
||||
cop.ntcrNm = Noticer Name
|
||||
cop.password = PassWord
|
||||
cop.atchFile = Attach Files
|
||||
cop.guestList = Guest List
|
||||
cop.guestListCn = Guest List Contents
|
||||
cop.noticeTerm = Notice term
|
||||
cop.atchFileList = Attached File List
|
||||
cop.cmmntyNm = Community Name
|
||||
cop.cmmntyIntrcn = Community Introduction
|
||||
cop.cmmntyMngr = Community Manager
|
||||
cop.clbOprtr = Club Operator
|
||||
cop.clbIntrcn = Club Introduction
|
||||
cop.clbNm = Club Name
|
||||
cop.tmplatNm = Template Name
|
||||
cop.tmplatSeCode = Template Se Code
|
||||
cop.tmplatCours = Template Cours
|
||||
cop.useAt = Use Alternative
|
||||
cop.ncrdNm = NameCard user name
|
||||
cop.cmpnyNm = Company name
|
||||
cop.deptNm = Department name
|
||||
cop.ofcpsNm = OFCPS name
|
||||
cop.clsfNm = Class Name
|
||||
cop.emailAdres = E-mail
|
||||
cop.telNo = Tel No.
|
||||
cop.mbtlNum = Mobile
|
||||
cop.adres = Address
|
||||
cop.extrlUserAt = External User alternative
|
||||
cop.publicAt = Public open alternative
|
||||
cop.remark = Remark
|
||||
cop.trgetNm = Company/Club Information
|
||||
cop.preview = preview
|
||||
|
||||
cop.withdraw.msg=confirm withdrawal memebership?
|
||||
cop.reregist.msg=confirm re-registration?
|
||||
cop.registmanager.msg=confirm registration of manager?
|
||||
cop.use.msg=confirm use?
|
||||
cop.unuse.msg=confirm stop using?
|
||||
cop.delete.confirm.msg=If you choose to disable the re-use change is impossible.
|
||||
cop.ing.msg=Approval is being requested.
|
||||
cop.request.msg=Signup is normally requested.
|
||||
cop.password.msg=Please enter your password.
|
||||
cop.password.not.same.msg=Password do not match.
|
||||
|
||||
cop.comment.wrterNm = Writer Name
|
||||
cop.comment.commentCn = Comment
|
||||
cop.comment.commentPassword = Password
|
||||
|
||||
cop.satisfaction.wrterNm = Writer Name
|
||||
cop.satisfaction.stsfdgCn = Satisfaction
|
||||
cop.satisfaction.stsfdg = Satisfaction Degree
|
||||
cop.satisfaction.stsfdgPassword = Password
|
||||
|
||||
cop.scrap.scrapNm = Scrap Name
|
||||
|
||||
#UI USS Message#
|
||||
uss.ion.noi.ntfcSj=Subject
|
||||
uss.ion.noi.ntfcCn=Contents
|
||||
uss.ion.noi.ntfcDate=Notification Date
|
||||
uss.ion.noi.ntfcTime=Notification Time
|
||||
uss.ion.noi.ntfcHH=Notification Hour
|
||||
uss.ion.noi.ntfcMM=Notification Minute
|
||||
uss.ion.noi.bhNtfcIntrvl=Beforehand Interval
|
||||
uss.ion.noi.bhNtfcIntrvl.msg=Beforehand Interval is required.
|
||||
uss.ion.noi.alertNtfcTime=Date and time of notification is not valid.
|
||||
|
||||
#UI COP Message#
|
||||
cop.sms.trnsmitTelno=Sender
|
||||
cop.sms.trnsmitCn=Contents
|
||||
cop.sms.recptnTelno=Receiver(s)
|
||||
cop.sms.send=Send
|
||||
cop.sms.addRecptn=Add
|
||||
cop.sms.recptnTelno.msg=The phone number of receiver is required.
|
||||
|
||||
#UI sym.log Message#
|
||||
sym.log.histSeCode = History Code
|
||||
sym.log.sysNm = System Name
|
||||
sym.log.histCn = History Contents
|
||||
sym.log.atchFile = Attached File
|
||||
sym.log.atchFileList = Attached File List
|
||||
sym.ems.receiver = Receiver
|
||||
sym.ems.title = Title
|
||||
sym.ems.content = Content
|
||||
|
||||
#Vlidator Errors#
|
||||
errors.required={0} is required.
|
||||
errors.minlength={0} can not be less than {1} characters.
|
||||
errors.maxlength={0} can not be greater than {1} characters.
|
||||
errors.invalid={0} is invalid.
|
||||
|
||||
errors.byte={0} must be a byte.
|
||||
errors.short={0} must be a short.
|
||||
errors.integer={0} must be an integer.
|
||||
errors.long={0} must be a long.
|
||||
errors.float={0} must be a float.
|
||||
errors.double={0} must be a double.
|
||||
|
||||
errors.date={0} is not a date.
|
||||
errors.range={0} is not in the range {1} through {2}.
|
||||
errors.creditcard={0} is an invalid credit card number.
|
||||
errors.email={0} is an invalid e-mail address.
|
||||
|
||||
#Vlidator Errors- ReprtStatsVO#
|
||||
sts.reprtId = Report ID
|
||||
sts.title = Report Title
|
||||
sts.category = Report Category
|
||||
sts.status = Report Status
|
||||
sts.regDate = Registration Date
|
||||
|
||||
#Rest day messages#
|
||||
sym.cal.restDay = Holiday Date
|
||||
sym.cal.restName = Holiday Name
|
||||
sym.cal.restDetail = Holiday Detail
|
||||
sym.cal.restCategory = Holiday Category
|
||||
|
||||
|
||||
#Custom message#
|
||||
custom.fail.access=It's not a normal approach. Log in and use it.
|
||||
custom.fail.accessDenied=You do not have permission to request.
|
||||
custom.isNotExist.msg=Data required for processing does not exist.
|
@ -0,0 +1,375 @@
|
||||
fail.common.msg=\uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4!
|
||||
fail.common.sql=sql \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4! error code: {0}, error msg: {1}
|
||||
info.nodata.msg=\ud574\ub2f9 \ub370\uc774\ud130\uac00 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#UI Common resource#
|
||||
table.num=\ubc88\ud638
|
||||
table.regdate=\ub4f1\ub85d\uc77c
|
||||
table.reger=\ub4f1\ub85d\uc790
|
||||
table.select=\uc120\ud0dd
|
||||
title.html=egovframe common component
|
||||
title.detail=\uc0c1\uc138\uc870\ud68c
|
||||
title.inquire=\uc870\ud68c
|
||||
title.update=\uc218\uc815
|
||||
title.create=\ub4f1\ub85d
|
||||
title.delete=\uc0ad\uc81c
|
||||
title.save=\uc800\uc7a5
|
||||
title.list=\ubaa9\ub85d
|
||||
title.searchCondition=\uac80\uc0c9\uc870\uac74
|
||||
title.search=\uac80\uc0c9\uc5b4
|
||||
title.reply=\ub2f5\uae00
|
||||
title.scrap=\uc2a4\ud06c\ub7a9
|
||||
title.comment=\ub313\uae00
|
||||
title.attachedFileSelect=\ud30c\uc77c\uc120\ud0dd
|
||||
title.attachedFileDelete=\ud30c\uc77c\uc0ad\uc81c
|
||||
title.link=\ub9c1\ud06c
|
||||
title.management=\uad00\ub9ac
|
||||
title.all=\uc804\uccb4
|
||||
|
||||
input.select=\uc120\ud0dd\ud558\uc138\uc694
|
||||
input.cSelect=\uc120\ud0dd
|
||||
input.input=\uc785\ub825
|
||||
input.button=\ubc84\ud2bc
|
||||
input.selectAll.title=\uc804\uccb4\uc120\ud0dd\uccb4\ud06c\ubc15\uc2a4
|
||||
input.yes=\uc608
|
||||
input.no=\uc544\ub2c8\uc624
|
||||
|
||||
select.searchCondition=\uc870\ud68c\uc870\uac74 \uc120\ud0dd
|
||||
|
||||
button.select=\uc120\ud0dd
|
||||
button.search=\uac80\uc0c9
|
||||
button.use=\uc0ac\uc6a9
|
||||
button.notUsed=\uc0ac\uc6a9\uc911\uc9c0
|
||||
button.inquire=\uc870\ud68c
|
||||
button.update=\uc218\uc815
|
||||
button.create=\ub4f1\ub85d
|
||||
button.delete=\uc0ad\uc81c
|
||||
button.deleteDatabase=\uc644\uc804\uc0ad\uc81c
|
||||
button.close=\ub2eb\uae30
|
||||
button.save=\uc800\uc7a5
|
||||
button.list=\ubaa9\ub85d
|
||||
button.reset=\ucde8\uc18c
|
||||
button.passwordUpdate=\uc554\ud638\ubcc0\uacbd
|
||||
button.subscribe=\uac00\uc785\uc2e0\uccad
|
||||
button.realname=\uc2e4\uba85\ud655\uc778
|
||||
button.moveToGpin=GPIN\uc2e4\uba85\ud655\uc778\uc73c\ub85c \uc774\ub3d9
|
||||
button.moveToIhidnum=\uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638 \uc2e4\uba85\ud655\uc778\uc73c\ub85c \uc774\ub3d9
|
||||
button.agree=\ub3d9\uc758
|
||||
button.disagree=\ube44\ub3d9\uc758
|
||||
button.possible=\uac00\ub2a5
|
||||
button.impossible=\ubd88\uac00\ub2a5
|
||||
button.qnaregist=Q&A\ub4f1\ub85d
|
||||
button.cnsltregist=\uc0c1\ub2f4\ub4f1\ub85d
|
||||
button.preview=\ubbf8\ub9ac\ubcf4\uae30
|
||||
button.next=\ub2e4\uc74c
|
||||
button.add=\ubc14\ub85c\ucd94\uac00
|
||||
button.confirm=\ud655\uc778
|
||||
button.back = \ub4a4\ub85c
|
||||
button.yes = \uc608
|
||||
button.no = \uc544\ub2c8\uc624
|
||||
button.home = \ud648
|
||||
button.user = \uc0ac\uc6a9\uc790\uc9c0\uc6d0
|
||||
button.cop = \ud611\uc5c5
|
||||
button.wrkstart = \ucd9c\uadfc
|
||||
button.wrkend = \ud1f4\uadfc
|
||||
button.reply = \ub2f5\uae00
|
||||
button.scrap = \uc2a4\ud06c\ub7a9
|
||||
button.comment = \ub313\uae00
|
||||
button.excel = \uc5d1\uc140
|
||||
button.init=\ucd08\uae30\ud654
|
||||
button.acknowledgment=\uc2b9\uc778
|
||||
button.cancelAcknowledgment=\uc2b9\uc778\ucde8\uc18c
|
||||
button.bulkUpload=\uc77c\uad04\ub4f1\ub85d
|
||||
button.log = \ub85c\uadf8
|
||||
button.set = \uc124\uc815
|
||||
button.move = \uc774\ub3d9
|
||||
|
||||
|
||||
#UI Common Message#
|
||||
common.noScriptTitle.msg=\uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8\ub97c \uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c\ub294 \uc77c\ubd80 \uae30\ub2a5\uc744 \uc0ac\uc6a9\ud558\uc2e4 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
common.searchCondition.msg=\uc774 \ub808\uc774\uc544\uc6c3\uc740 \ud558\ub2e8 \uc815\ubcf4\ub97c \ub300\ud55c \uac80\uc0c9 \uc815\ubcf4\ub85c \uad6c\uc131\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
common.summary.list={0}\uc758 \ub0b4\uc5ed\uc5d0 \ub300\ud55c \ubaa9\ub85d\uc744 \ucd9c\ub825\ud569\ub2c8\ub2e4.
|
||||
common.summary.regist={0}\uc758 \ub4f1\ub85d \uac00\ub2a5\ud55c \ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc5ec \ub4f1\ub85d \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \ub4f1\ub85d\ud55c\ub2e4.
|
||||
common.summary.update={0}\uc758 \ub4f1\ub85d \uac00\ub2a5\ud55c \ub0b4\uc6a9\uc744 \uc785\ub825\ud558\uc5ec \ub4f1\ub85d \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \uc218\uc815\ud55c\ub2e4.
|
||||
common.summary.inqire={0}\uc758 \ub0b4\uc5ed\uc5d0 \ub300\ud55c \uc0c1\uc138\uc870\ud68c \ub0b4\uc5ed\uc744 \ucd9c\ub825\ud569\ub2c8\ub2e4.
|
||||
|
||||
common.save.msg=\uc800\uc7a5\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.regist.msg=\ub4f1\ub85d\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.delete.msg=\uc0ad\uc81c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.update.msg=\uc218\uc815\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.nodata.msg=\uc790\ub8cc\uac00 \uc5c6\uc2b5\ub2c8\ub2e4. \ub2e4\ub978 \uac80\uc0c9\uc870\uac74\uc744 \uc120\ud0dd\ud574\uc8fc\uc138\uc694
|
||||
common.required.msg=(\uc740)\ub294 \ud544\uc218\uc785\ub825\ud56d\ubaa9\uc785\ub2c8\ub2e4.
|
||||
common.acknowledgement.msg=\uc2b9\uc778\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.acknowledgementcancel.msg=\uc2b9\uc778\ucde8\uc18c\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
common.nocomment.msg=\ub313\uae00\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
common.noguest.msg=\uc791\uc131\ub41c \ubc29\uba85\ub85d\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
success.request.msg = \uc694\uccad\ucc98\ub9ac\uac00 \uc131\uacf5\uc801\uc73c\ub85c \uc218\ud589\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
success.common.select=\uc815\uc0c1\uc801\uc73c\ub85c \uc870\ud68c\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
success.common.insert=\uc815\uc0c1\uc801\uc73c\ub85c \ub4f1\ub85d\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
success.common.update=\uc815\uc0c1\uc801\uc73c\ub85c \uc218\uc815\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
success.common.delete=\uc815\uc0c1\uc801\uc73c\ub85c \uc0ad\uc81c\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
common.imposbl.fileupload = \ub354 \uc774\uc0c1 \ud30c\uc77c\uc744 \ucca8\ubd80\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
common.isConfmDe.msg=\uc2b9\uc778\uc77c\uc790\ub97c \ud655\uc778 \ubc14\ub78d\ub2c8\ub2e4.
|
||||
common.isExist.msg = \uc774\ubbf8 \uc874\uc7ac\ud558\uac70\ub098 \uacfc\uac70\uc5d0 \ub4f1\ub85d\uc774 \ub418\uc5c8\ub358 \uc0c1\ud0dc\uc785\ub2c8\ub2e4.
|
||||
|
||||
fail.common.insert = \uc0dd\uc131\uc774 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.update = \uc218\uc815\uc774 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.delete = \uc0ad\uc81c\uac00 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.delete.upperMenuExist = \ucc38\uc870\ub418\ub294 \uba54\ub274\uac00 \uc788\uc5b4 \uc0ad\uc81c\uac00 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.select = \uc870\ud68c\uc5d0 \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.login = \ub85c\uadf8\uc778 \uc815\ubcf4\uac00 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.loginIncorrect = {0}\ud68c \uc774\uc0c1 \ub85c\uadf8\uc778 \uc811\uc18d\uc774 \uc2dc\ub3c4 \ub418\uc5b4 \uacc4\uc815\uc774 \uc7a0\uaca8\uc2b5\ub2c8\ub2e4!
|
||||
fail.common.login.password = \ud328\uc2a4\uc6cc\ub4dc \uc790\ub9ac \uc218\uac00 \uc77c\uce58 \ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.(8\uc790\ub9ac \uc774\uc0c1 20\uc790\ub9ac \uc774\ud558)
|
||||
fail.common.idsearch = \uc544\uc774\ub514\ub97c \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.pwsearch = \ube44\ubc00\ubc88\ud638\ub97c \ucc3e\uc744\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
fail.request.msg = \uc694\uccad\ucc98\ub9ac\ub97c \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.
|
||||
fail.common.login.ip = \ub4f1\ub85d\ub41c IP\uac00 \uc544\ub2c8\ubbc0\ub85c \ub85c\uadf8\uc778\uc774 \uac70\ubd80\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#UI User Message#
|
||||
fail.user.passwordUpdate1=\ud604\uc7ac \ube44\ubc00\ubc88\ud638\uac00 \ub9de\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
fail.user.passwordUpdate2=\ube44\ubc00\ubc88\ud638\uc640 \ube44\ubc00\ubc88\ud638 \ud655\uc778\uc774 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
info.user.rlnmCnfirm=\uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc2e4\uba85\ud655\uc778\uc744 \ud558\uc2ed\uc2dc\uc624.
|
||||
success.user.rlnmCnfirm=\ud589\uc815\uc548\uc804\ubd80\uc758 \uc8fc\ubbfc\ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud569\ub2c8\ub2e4.
|
||||
fail.user.rlnmCnfirm=\ud589\uc815\uc548\uc804\ubd80\uc758 \uc8fc\ubbfc\ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
fail.user.connectFail=\uc2dc\uc2a4\ud15c \uc7a5\uc560\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.(\uc778\uc99d\uc11c\ubc84 \uc5f0\uacb0 \uc2e4\ud328)
|
||||
info.user.rlnmPinCnfirm=\uacf5\uacf5 \uc544\uc774\ud540 \uc544\uc774\ub514\ub97c \uc0ac\uc6a9\ud558\uc5ec \uc2e4\uba85\ud655\uc778\uc744 \ud558\uc2ed\uc2dc\uc624.
|
||||
success.user.rlnmPinCnfirm=\uacf5\uacf5\uc544\uc774\ud540\uc758 \ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud569\ub2c8\ub2e4.
|
||||
fail.user.rlnmPinCnfirm=\uacf5\uacf5\uc544\uc774\ud540\uc758 \ub4f1\ub85d\uc790\ub8cc\uc640 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
|
||||
#UI Cop Message#
|
||||
cop.extrlUser = \uc678\ubd80\uc0ac\uc6a9\uc790
|
||||
cop.intrlUser = \ub0b4\ubd80\uc0ac\uc6a9\uc790
|
||||
cop.private = \ube44\uacf5\uac1c
|
||||
cop.public = \uacf5\uac1c
|
||||
|
||||
cop.adbkNm = \uc8fc\uc18c\ub85d\uba85
|
||||
cop.othbcScope = \uacf5\uac1c\ubc94\uc704
|
||||
cop.company = \ud68c\uc0ac
|
||||
cop.part = \ubd80\uc11c
|
||||
cop.man = \uac1c\uc778
|
||||
cop.adbkUser = \uad6c\uc131\uc6d0
|
||||
cop.bbsNm = \uac8c\uc2dc\ud310\uba85
|
||||
cop.bbsIntrcn = \uac8c\uc2dc\ud310\uc18c\uac1c
|
||||
cop.bbsTyCode = \uac8c\uc2dc\ud310 \uc720\ud615
|
||||
cop.bbsAttrbCode = \uac8c\uc2dc\ud310 \uc18d\uc131
|
||||
cop.replyPosblAt = \ub2f5\uc7a5\uac00\ub2a5\uc5ec\ubd80
|
||||
cop.fileAtchPosblAt = \ud30c\uc77c\ucca8\ubd80\uac00\ub2a5\uc5ec\ubd80
|
||||
cop.posblAtchFileNumber = \ucca8\ubd80\uac00\ub2a5\ud30c\uc77c \uc22b\uc790
|
||||
cop.tmplatId = \ud15c\ud50c\ub9bf \uc815\ubcf4
|
||||
cop.guestList.subject = \ubc29\uba85\ub85d \uac8c\uc2dc\uae00\uc785\ub2c8\ub2e4.
|
||||
cop.nttSj = \uc81c\ubaa9
|
||||
cop.nttCn = \uae00\ub0b4\uc6a9
|
||||
cop.ntceBgnde = \uac8c\uc2dc\uc2dc\uc791\uc77c
|
||||
cop.ntceEndde = \uac8c\uc2dc\uc885\ub8cc\uc77c
|
||||
cop.ntcrNm = \uc791\uc131\uc790
|
||||
cop.password = \ud328\uc2a4\uc6cc\ub4dc
|
||||
cop.atchFile = \ud30c\uc77c\ucca8\ubd80
|
||||
cop.guestList = \ubc29\uba85\ub85d
|
||||
cop.guestListCn = \ubc29\uba85\ub85d \ub0b4\uc6a9
|
||||
cop.noticeTerm = \uac8c\uc2dc\uae30\uac04
|
||||
cop.atchFileList = \ucca8\ubd80\ud30c\uc77c\ubaa9\ub85d
|
||||
cop.cmmntyNm = \ucee4\ubba4\ub2c8\ud2f0\uba85
|
||||
cop.cmmntyIntrcn = \ucee4\ubba4\ub2c8\ud2f0 \uc18c\uac1c
|
||||
cop.cmmntyMngr = \ucee4\ubba4\ub2c8\ud2f0 \uad00\ub9ac\uc790
|
||||
cop.clbOprtr = \ub3d9\ud638\ud68c \uc6b4\uc601\uc790
|
||||
cop.clbIntrcn = \ub3d9\ud638\ud68c \uc18c\uac1c
|
||||
cop.clbNm = \ub3d9\ud638\ud68c \uba85
|
||||
cop.tmplatNm = \ud15c\ud50c\ub9bf\uba85
|
||||
cop.tmplatSeCode = \ud15c\ud50c\ub9bf \uad6c\ubd84
|
||||
cop.tmplatCours = \ud15c\ud50c\ub9bf\uacbd\ub85c
|
||||
cop.useAt = \uc0ac\uc6a9\uc5ec\ubd80
|
||||
cop.ncrdNm = \uc774\ub984
|
||||
cop.cmpnyNm = \ud68c\uc0ac\uba85
|
||||
cop.deptNm = \ubd80\uc11c\uba85
|
||||
cop.ofcpsNm = \uc9c1\uc704
|
||||
cop.clsfNm = \uc9c1\uae09
|
||||
cop.emailAdres = \uc774\uba54\uc77c\uc8fc\uc18c
|
||||
cop.telNo = \uc804\ud654\ubc88\ud638
|
||||
cop.mbtlNum = \ud734\ub300\ud3f0\ubc88\ud638
|
||||
cop.adres = \uc8fc\uc18c
|
||||
cop.extrlUserAt = \uc678\ubd80\uc0ac\uc6a9\uc790\uc5ec\ubd80
|
||||
cop.publicAt = \uacf5\uac1c\uc5ec\ubd80
|
||||
cop.remark = \ube44\uace0
|
||||
cop.trgetNm = \ucee4\ubba4\ub2c8\ud2f0/\ub3d9\ud638\ud68c \uc815\ubcf4
|
||||
cop.preview = \ubbf8\ub9ac\ubcf4\uae30
|
||||
|
||||
cop.withdraw.msg=\ud0c8\ud1f4\ucc98\ub9ac \ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.reregist.msg=\uc7ac\uac00\uc785 \ucc98\ub9ac\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.registmanager.msg=\uc6b4\uc601\uc9c4\uc73c\ub85c \ub4f1\ub85d\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.use.msg=\uc0ac\uc6a9 \ucc98\ub9ac\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.unuse.msg=\uc0ac\uc6a9\uc911\uc9c0 \ucc98\ub9ac\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?
|
||||
cop.delete.confirm.msg=\uc0ac\uc6a9\uc911\uc9c0\ub97c \uc120\ud0dd\ud558\uc2e4 \uacbd\uc6b0 \ub2e4\uc2dc \uc0ac\uc6a9\uc73c\ub85c \ubcc0\uacbd\uc774 \ubd88\uac00\ub2a5\ud569\ub2c8\ub2e4.
|
||||
cop.ing.msg=\uc2b9\uc778\uc694\uccad \uc911\uc785\ub2c8\ub2e4.
|
||||
cop.request.msg=\uac00\uc785\uc2e0\uccad\uc774 \uc815\uc0c1\uc801\uc73c\ub85c \uc694\uccad\ub418\uc5c8\uc2b5\ub2c8\ub2e4
|
||||
cop.password.msg=\ud328\uc2a4\uc6cc\ub4dc\ub97c \uc785\ub825\ud574 \uc8fc\uc2ed\uc2dc\uc624.
|
||||
cop.password.not.same.msg=\ud328\uc2a4\uc6cc\ub4dc\uac00 \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
cop.comment.wrterNm = \uc791\uc131\uc790
|
||||
cop.comment.commentCn = \ub0b4\uc6a9
|
||||
cop.comment.commentPassword = \ud328\uc2a4\uc6cc\ub4dc
|
||||
|
||||
cop.satisfaction.wrterNm = \uc791\uc131\uc790
|
||||
cop.satisfaction.stsfdgCn = \ub0b4\uc6a9
|
||||
cop.satisfaction.stsfdg = \ub9cc\uc871\ub3c4
|
||||
cop.satisfaction.stsfdgPassword = \ud328\uc2a4\uc6cc\ub4dc
|
||||
|
||||
cop.scrap.scrapNm = \uc2a4\ud06c\ub7a9\uba85
|
||||
|
||||
#UI USS Message#
|
||||
uss.ion.noi.ntfcSj=\uc81c\ubaa9
|
||||
uss.ion.noi.ntfcCn=\ub0b4\uc6a9
|
||||
uss.ion.noi.ntfcDate=\uc54c\ub9bc\uc77c\uc790
|
||||
uss.ion.noi.ntfcTime=\uc54c\ub9bc\uc2dc\uac04
|
||||
uss.ion.noi.ntfcHH=\uc54c\ub9bc\uc2dc\uac04
|
||||
uss.ion.noi.ntfcMM=\uc54c\ub9bc\ubd84
|
||||
uss.ion.noi.bhNtfcIntrvl=\uc0ac\uc804\uc54c\ub9bc\uac04\uaca9
|
||||
uss.ion.noi.bhNtfcIntrvl.msg=\uc0ac\uc804\uc54c\ub9bc\uac04\uaca9 \uc9c0\uc815\uc774 \ud544\uc694\ud569\ub2c8\ub2e4.
|
||||
uss.ion.noi.alertNtfcTime=\uc54c\ub9bc\uc77c\uc790 \ubc0f \uc2dc\uac04\uc774 \uc720\ud6a8\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#UI COP Message#
|
||||
cop.sms.trnsmitTelno=\ubc1c\uc2e0\uc804\ud654\ubc88\ud638
|
||||
cop.sms.trnsmitCn=\uc804\uc1a1\ub0b4\uc6a9
|
||||
cop.sms.recptnTelno=\uc218\uc2e0\uc804\ud654\ubc88\ud638
|
||||
cop.sms.send=\uc804\uc1a1
|
||||
cop.sms.addRecptn=\ucd94\uac00
|
||||
cop.sms.recptnTelno.msg=\uc218\uc2e0\uc804\ud654\ubc88\ud638 \uc9c0\uc815\uc774 \ud544\uc694\ud569\ub2c8\ub2e4.
|
||||
|
||||
#UI sym.log Message#
|
||||
sym.log.histSeCode = \uc774\ub825\uad6c\ubd84
|
||||
sym.log.sysNm = \uc2dc\uc2a4\ud15c\uba85
|
||||
sym.log.histCn = \uc774\ub825\ub0b4\uc6a9
|
||||
sym.log.atchFile = \ucca8\ubd80\ud30c\uc77c
|
||||
sym.log.atchFileList = \ucca8\ubd80\ud30c\uc77c\ubaa9\ub85d
|
||||
sym.ems.receiver = \ubc1b\ub294\uc0ac\ub78c
|
||||
sym.ems.title = \uc81c\ubaa9
|
||||
sym.ems.content = \ubc1c\uc2e0\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors#
|
||||
errors.prefix=<div class="error">
|
||||
errors.suffix=</div><br/>
|
||||
|
||||
errors.required={0}\uc740(\ub294) \ud544\uc218 \uc785\ub825\uac12\uc785\ub2c8\ub2e4.
|
||||
errors.minlength={0}\uc740(\ub294) {1}\uc790 \uc774\uc0c1 \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.maxlength={0}\uc740(\ub294) {1}\uc790 \uc774\uc0c1 \uc785\ub825\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
errors.invalid={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uac12\uc785\ub2c8\ub2e4.
|
||||
errors.minInteger={0}\uc740(\ub294) \uc720\ud6a8\ud55c \uac12\uc774 \uc544\ub2d9\ub2c8\ub2e4. 1 \uc774\uc0c1\uc758 \uac12\uc744 \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.byte={0}\uc740(\ub294) byte\ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.short={0}\uc740(\ub294) short\ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.integer={0}\uc740(\ub294) \uc815\uc218 \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.long={0}\uc740(\ub294) long \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.float={0}\uc740(\ub294) \uc2e4\uc218 \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.double={0}\uc740(\ub294) double \ud0c0\uc785\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
|
||||
errors.date={0}\uc740(\ub294) \ub0a0\uc9dc \uc720\ud615\uc774 \uc544\ub2d9\ub2c8\ub2e4.
|
||||
errors.range={0}\uc740(\ub294) {1}\uacfc {2} \uc0ac\uc774\uc758 \uac12\uc774\uc5b4\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.creditcard={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc2e0\uc6a9\uce74\ub4dc \ubc88\ud638\uc785\ub2c8\ub2e4.
|
||||
errors.email={0}\uc740(\ub294) \uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc774\uba54\uc77c \uc8fc\uc18c\uc785\ub2c8\ub2e4.
|
||||
|
||||
errors.ihidnum=\uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 \uc8fc\ubbfc\ub4f1\ub85d\ubc88\ud638\uc785\ub2c8\ub2e4.
|
||||
errors.korean={0}\uc740(\ub294) \ud55c\uae00\uc744 \uc785\ub825\ud558\uc154\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.ip=\uc720\ud6a8\ud558\uc9c0 \uc54a\uc740 IP\uc8fc\uc18c\uc785\ub2c8\ub2e4.
|
||||
|
||||
errors.password1={0}\uc740(\ub294) 8~20\uc790 \ub0b4\uc5d0\uc11c \uc785\ub825\ud574\uc57c \ud569\ub2c8\ub2e4.
|
||||
errors.password2={0}\uc740(\ub294) \ud55c\uae00,\ud2b9\uc218\ubb38\uc790,\ub744\uc5b4\uc4f0\uae30\ub294 \ud5c8\uc6a9\ub418\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
||||
errors.password3={0}\uc740(\ub294) \uc21c\ucc28\uc801\uc778 \uc22b\uc790\ub97c 4\uac1c\uc774\uc0c1 \uc5f0\uc18d\ud574\uc11c \uc0ac\uc6a9\ud560\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
errors.password4={0}\uc740(\ub294) \ubc18\ubcf5\ub418\ub294 \ubb38\uc790\ub098 \uc22b\uc790\ub97c 4\uac1c\uc774\uc0c1 \uc5f0\uc18d\ud574\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
errors.notKorean={0}\uc740(\ub294) \ud55c\uae00\uc744 \uc0ac\uc6a9\ud558\uc2e4\uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
error.security.runtime.error = error
|
||||
|
||||
#Xss Errors#
|
||||
errors.xss.checkerUser=\ud574\ub2f9 \uae30\ub2a5\uc5d0 \ub300\ud55c \uc0ac\uc6a9 \ubc0f \ucc98\ub9ac \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#File Upload / Download
|
||||
errors.file.extension=\uc9c0\uc6d0\ub418\ub294 \ud30c\uc77c\uc720\ud615\uc774 \uc544\ub2d9\ub2c8\ub2e4.
|
||||
errors.file.transfer=\ud30c\uc77c\uc804\uc1a1\uc911 \uc624\ub958\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.
|
||||
success.file.transfer=\ud30c\uc77c\uc804\uc1a1\uc774 \uc644\ub8cc\ub418\uc5c8\uc2b5\ub2c8\ub2e4.
|
||||
|
||||
#Vlidator Errors- wordDicaryVO#
|
||||
wordDicaryVO.wordNm=\uc6a9\uc5b4\uba85
|
||||
wordDicaryVO.engNm=\uc601\ubb38\uba85
|
||||
wordDicaryVO.wordDc=\uc6a9\uc5b4\uc124\uba85
|
||||
wordDicaryVO.synonm=\ub3d9\uc758\uc5b4
|
||||
|
||||
#Vlidator Errors- cnsltManageVO#
|
||||
cnsltManageVO.cnsltSj=\uc0c1\ub2f4\uc81c\ubaa9
|
||||
cnsltManageVO.cnsltCn=\uc0c1\ub2f4\ub0b4\uc6a9
|
||||
cnsltManageVO.writngPassword=\uc791\uc131\ube44\ubc00\ubc88\ud638
|
||||
cnsltManageVO.areaNo=\uc9c0\uc5ed\ubc88\ud638
|
||||
cnsltManageVO.middleTelno=\uc911\uac04\uc804\ud654\ubc88\ud638
|
||||
cnsltManageVO.endTelno=\ub05d\uc804\ud654\ubc88\ud638
|
||||
cnsltManageVO.wrterNm=\uc791\uc131\uc790\uba85
|
||||
cnsltManageVO.managtCn=\ub2f5\ubcc0\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- siteManageVO#
|
||||
siteManageVO.siteNm=\uc0ac\uc774\ud2b8\uba85
|
||||
siteManageVO.siteUrl=\uc0ac\uc774\ud2b8 URL
|
||||
siteManageVO.siteDc=\uc0ac\uc774\ud2b8\uc124\uba85
|
||||
siteManageVO.siteThemaClCode=\uc0ac\uc774\ud2b8\uc8fc\uc81c\ubd84\ub958
|
||||
siteManageVO.actvtyAt=\ud65c\uc131\uc5ec\ubd80
|
||||
siteManageVO.useAt=\uc0ac\uc6a9\uc5ec\ubd80
|
||||
|
||||
#Vlidator Errors- recomendSiteManageVO#
|
||||
recomendSiteManageVO.recomendSiteNm=\ucd94\ucc9c\uc0ac\uc774\ud2b8\uba85
|
||||
recomendSiteManageVO.recomendSiteUrl=\ucd94\ucc9c\uc0ac\uc774\ud2b8 URL
|
||||
recomendSiteManageVO.recomendSiteDc=\ucd94\ucc9c\uc0ac\uc774\ud2b8\uc124\uba85
|
||||
recomendSiteManageVO.recomendResnCn=\ucd94\ucc9c\uc0ac\uc774\ud2b8\uc2b9\uc778\uc0ac\uc720
|
||||
recomendSiteManageVO.confmDe=\uc2b9\uc778\uc77c\uc790
|
||||
|
||||
#Vlidator Errors- hpcmManageVO#
|
||||
hpcmManageVO.hpcmSeCode=\ub3c4\uc6c0\ub9d0\uad6c\ubd84
|
||||
hpcmManageVO.hpcmDf=\ub3c4\uc6c0\ub9d0\uc815\uc758
|
||||
hpcmManageVO.hpcmDc=\ub3c4\uc6c0\ub9d0\uc124\uba85
|
||||
|
||||
#Vlidator Errors- newsManageVO#
|
||||
newsManageVO.newsSj=\ub274\uc2a4\uc81c\ubaa9
|
||||
newsManageVO.newsCn=\ub274\uc2a4\ub0b4\uc6a9
|
||||
newsManageVO.ntceDe=\uac8c\uc2dc\uc77c\uc790
|
||||
|
||||
#Vlidator Errors- faqManageVO#
|
||||
faqManageVO.qestnSj=\uc9c8\ubb38\uc81c\ubaa9
|
||||
faqManageVO.qestnCn=\uc9c8\ubb38\ub0b4\uc6a9
|
||||
faqManageVO.answerCn=\ub2f5\ubcc0\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- stplatManageVO#
|
||||
stplatManageVO.useStplatNm=\uc774\uc6a9\uc57d\uad00\uba85
|
||||
stplatManageVO.useStplatCn=\uc774\uc6a9\uc57d\uad00\ub0b4\uc6a9
|
||||
stplatManageVO.infoProvdAgreCn=\uc815\ubcf4\uc81c\uacf5\ub3d9\uc758\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- cpyrhtPrtcPolicyVO#
|
||||
cpyrhtPrtcPolicyVO.cpyrhtPrtcPolicyCn=\uc800\uc791\uad8c\ubcf4\ud638\uc815\ucc45\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- qnaManageVO#
|
||||
qnaManageVO.qestnSj=\uc9c8\ubb38\uc81c\ubaa9
|
||||
qnaManageVO.qestnCn=\uc9c8\ubb38\ub0b4\uc6a9
|
||||
qnaManageVO.writngPassword=\uc791\uc131\ube44\ubc00\ubc88\ud638
|
||||
qnaManageVO.areaNo=\uc9c0\uc5ed\ubc88\ud638
|
||||
qnaManageVO.middleTelno=\uc911\uac04\uc804\ud654\ubc88\ud638
|
||||
qnaManageVO.endTelno=\ub05d\uc804\ud654\ubc88\ud638
|
||||
qnaManageVO.wrterNm=\uc791\uc131\uc790\uba85
|
||||
qnaManageVO.answerCn=\ub2f5\ubcc0\ub0b4\uc6a9
|
||||
|
||||
#Vlidator Errors- ReprtStatsVO#
|
||||
sts.reprtId = \ubcf4\uace0\uc11cID
|
||||
sts.title = \ubcf4\uace0\uc11c\uba85
|
||||
sts.category = \ubcf4\uace0\uc11c\uc720\ud615
|
||||
sts.status = \uc9c4\ud589\uc0c1\ud0dc
|
||||
sts.regDate = \ub4f1\ub85d\uc77c\uc2dc
|
||||
|
||||
#Rest day messages#
|
||||
sym.cal.restDay = \ud734\uc77c\uc77c\uc790
|
||||
sym.cal.restName = \ud734\uc77c\uba85
|
||||
sym.cal.restDetail = \ud734\uc77c\uc124\uba85
|
||||
sym.cal.restCategory = \ud734\uc77c\uad6c\ubd84
|
||||
|
||||
image.errorBg = \uc624\ub958\uc774\ubbf8\uc9c0
|
||||
|
||||
|
||||
#Custom message#
|
||||
custom.fail.access=\uc815\uc0c1\uc801\uc778 \uc811\uadfc\uc774 \uc544\ub2d9\ub2c8\ub2e4. \ub85c\uadf8\uc778 \ud6c4 \uc774\uc6a9\ud558\uc138\uc694.
|
||||
custom.fail.accessDenied=\uc694\uccad\uc5d0 \ub300\ud55c \uad8c\ud55c\uc774 \uc5c6\uc2b5\ub2c8\ub2e4.
|
||||
custom.isNotExist.msg=\ucc98\ub9ac\uc5d0 \ud544\uc694\ud55c \uc790\ub8cc\uac00 \uc874\uc7ac\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.
|
@ -0,0 +1,9 @@
|
||||
<?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:context="http://www.springframework.org/schema/context"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
</beans>
|
@ -0,0 +1,68 @@
|
||||
<?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:context="http://www.springframework.org/schema/context"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
|
||||
|
||||
<context:component-scan base-package="cokr.xit">
|
||||
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
|
||||
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
|
||||
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
|
||||
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
|
||||
</context:component-scan>
|
||||
|
||||
<bean id="antPathMatcher" class="org.springframework.util.AntPathMatcher" />
|
||||
|
||||
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
|
||||
<property name="basenames">
|
||||
<list>
|
||||
<value>classpath:message/message-common</value>
|
||||
<value>classpath:message/authentication-message</value>
|
||||
<value>classpath:org/egovframe/rte/fdl/property/messages/properties</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="defaultEncoding" value="UTF-8"/>
|
||||
<property name="cacheSeconds">
|
||||
<value>60</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
|
||||
<property name="dateFormat" ref="dateFormat"/>
|
||||
</bean>
|
||||
<bean id="dateFormat" class="java.text.SimpleDateFormat">
|
||||
<constructor-arg index="0" value="yyyy-MM-dd HH:mm"/>
|
||||
</bean>
|
||||
|
||||
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
|
||||
<property name="defaultLocale" value="ko_KR"/>
|
||||
</bean>
|
||||
|
||||
<bean name="propertyService" class="org.egovframe.rte.fdl.property.impl.EgovPropertyServiceImpl" destroy-method="destroy">
|
||||
<property name="properties">
|
||||
<map>
|
||||
<entry key="tempDir" value="D:/temp"/>
|
||||
|
||||
<entry key="pageUnit" value="10"/>
|
||||
<entry key="pageSize" value="10"/>
|
||||
</map>
|
||||
</property>
|
||||
<!--
|
||||
<property name="extFileName">
|
||||
<set>
|
||||
<map>
|
||||
<entry key="encoding" value="UTF-8"/>
|
||||
<entry key="filename" value="classpath*:properties/your-file.properties"/>
|
||||
</map>
|
||||
</set>
|
||||
</property>
|
||||
-->
|
||||
</bean>
|
||||
|
||||
<bean id="leaveaTrace" class="org.egovframe.rte.fdl.cmmn.trace.LeaveaTrace" />
|
||||
|
||||
</beans>
|
@ -0,0 +1,49 @@
|
||||
<?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:p="http://www.springframework.org/schema/p"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
|
||||
">
|
||||
|
||||
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
||||
<!--
|
||||
<property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"/>
|
||||
<property name="url" value="jdbc:oracle:thin:@115.21.123.118:1521:bustms" />
|
||||
-->
|
||||
<property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"/>
|
||||
<property name="url" value="jdbc:log4jdbc:mariadb://localhost:3306/xit-base?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul&useSSL=false" />
|
||||
<property name="username" value="root"/>
|
||||
<property name="password" value="mjkhan"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean"
|
||||
p:dataSource-ref="dataSource"
|
||||
p:configLocation="classpath:sql/mybatis-config.xml"
|
||||
p:mapperLocations="classpath:sql/mapper/**/*.xml"
|
||||
/>
|
||||
|
||||
<bean id="mapperConfigurer" class="org.egovframe.rte.psl.dataaccess.mapper.MapperConfigurer">
|
||||
<property name="basePackage" value="cokr.xit" />
|
||||
<property name="sqlSessionFactoryBeanName" value="sqlSession"/>
|
||||
</bean>
|
||||
|
||||
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
</bean>
|
||||
|
||||
<tx:advice id="txAdvice" transaction-manager="txManager">
|
||||
<tx:attributes>
|
||||
<tx:method name="*" rollback-for="Exception"/>
|
||||
</tx:attributes>
|
||||
</tx:advice>
|
||||
|
||||
<aop:config>
|
||||
<aop:pointcut id="serviceMethod" expression="execution(* cokr.xit..service.bean..*ServiceBean.*(..))" />
|
||||
<aop:pointcut id="requiredTx" expression="execution(* cokr.xit..service.bean..*ServiceBean.*(..))"/>
|
||||
<aop:advisor advice-ref="txAdvice" pointcut-ref="requiredTx" />
|
||||
</aop:config>
|
||||
|
||||
</beans>
|
@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:security="http://www.springframework.org/schema/security"
|
||||
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.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
|
||||
|
||||
<security:http pattern="/resources/**" security="none"/>
|
||||
|
||||
<security:http auto-config="true" create-session="never" use-expressions="true">
|
||||
<security:csrf />
|
||||
<security:headers />
|
||||
|
||||
<security:intercept-url pattern="/login.do" access="permitAll" />
|
||||
<security:intercept-url pattern="/error/*.do" access="permitAll" />
|
||||
<security:intercept-url pattern="/**" access="isAuthenticated()" />
|
||||
|
||||
<security:form-login
|
||||
login-page="/login.do"
|
||||
username-parameter="userId" password-parameter="password"
|
||||
authentication-details-source-ref="authenticationDetailsSource"
|
||||
|
||||
login-processing-url="/login.do"
|
||||
authentication-success-handler-ref="authenticationSuccess"
|
||||
authentication-failure-handler-ref="authenticationFailure"
|
||||
/>
|
||||
|
||||
<security:logout
|
||||
logout-url="/logout.do"
|
||||
success-handler-ref="logoutSuccess"
|
||||
/>
|
||||
|
||||
<security:session-management invalid-session-url="/error/sessionExpired.do">
|
||||
<security:concurrency-control expired-url="/error/sessionExpired.do" />
|
||||
</security:session-management>
|
||||
|
||||
</security:http>
|
||||
|
||||
<security:http-firewall ref="httpFirewall"/>
|
||||
<bean id="httpFirewall" class="org.springframework.security.web.firewall.DefaultHttpFirewall"/>
|
||||
|
||||
<security:authentication-manager >
|
||||
<security:authentication-provider ref="authenticationService"/>
|
||||
</security:authentication-manager>
|
||||
|
||||
<bean id="passwordEncoder" class="cokr.xit.base.security.authentication.service.bean.PasswordEncoder" />
|
||||
|
||||
<bean id="authenticationService" class="cokr.xit.base.security.authentication.service.bean.AuthenticationServiceBean">
|
||||
<property name="passwordEncoder" ref="passwordEncoder" />
|
||||
</bean>
|
||||
<bean id="authenticationDao" class="cokr.xit.base.security.authentication.dao.AuthenticationDao" />
|
||||
<bean id="authenticationDetailsSource" class="cokr.xit.base.security.authentication.web.AuthenticationExtraDetailsSource" />
|
||||
|
||||
<bean id="authenticationSuccess" class="cokr.xit.base.security.authentication.web.AuthenticationSuccess" />
|
||||
<bean id="authenticationFailure" class="cokr.xit.base.security.authentication.web.AuthenticationFailure" />
|
||||
<bean id="logoutSuccess" class="cokr.xit.base.security.authentication.web.LogoutSuccess" />
|
||||
|
||||
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<ref bean="applicationAccess"/>
|
||||
<bean class="org.springframework.security.web.access.expression.WebExpressionVoter"/>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
<bean id="applicationAccess" class="cokr.xit.base.security.access.ApplicationAccess">
|
||||
<property name="controlAccess" value="false"/>
|
||||
</bean>
|
||||
<bean id="accessContext" class="cokr.xit.base.security.access.AccessContext" />
|
||||
|
||||
</beans>
|
@ -0,0 +1,78 @@
|
||||
<?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">
|
||||
<mapper namespace="cokr.xit.base.security.access.dao.ActionGroupMapper">
|
||||
|
||||
<resultMap id="groupRow" type="cokr.xit.base.security.access.ActionGroup">
|
||||
<result property="id" column="GRP_ID"/>
|
||||
<result property="name" column="GRP_NM"/>
|
||||
<result property="description" column="DSCRP"/>
|
||||
<result property="createdAt" column="INS_DT"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectGroups"><include refid="utility.paging-prefix" />
|
||||
SELECT A.*
|
||||
FROM TBL_ACTION_GRP A
|
||||
<where>
|
||||
<if test="groupIDs != null">AND GRP_ID IN (<foreach collection="groupIDs" item="groupID" separator=",">#{groupID}</foreach>)</if>
|
||||
<if test="by != null and term != null">AND ${by} LIKE CONCAT('%', #{term}, '%')</if>
|
||||
</where>
|
||||
<include refid="utility.paging-suffix" /></sql>
|
||||
|
||||
<select id="getGroupList" parameterType="map" resultType="dataobject">/* 기능그룹 목록 조회(actionGroupMapper.getGroupList) */
|
||||
<include refid="selectGroups" /></select>
|
||||
|
||||
<select id="getGroups" parameterType="map" resultMap="groupRow">/* 기능그룹 가져오기(actionGroupMapper.getGroups) */
|
||||
<include refid="selectGroups" /></select>
|
||||
|
||||
<insert id="insertGroup" parameterType="cokr.xit.base.security.access.ActionGroup">/* 기능그룹 등록(actionGroupMapper.insertGroup) */
|
||||
INSERT INTO TBL_ACTION_GRP (
|
||||
GRP_ID
|
||||
, GRP_NM
|
||||
, DSCRP
|
||||
, INS_DT
|
||||
) VALUES (
|
||||
#{id}
|
||||
, #{name}
|
||||
, #{description}
|
||||
, CURRENT_TIMESTAMP()
|
||||
)</insert>
|
||||
|
||||
<update id="updateGroup" parameterType="cokr.xit.base.security.access.ActionGroup">/* 기능그룹 수정(actionGroupMapper.updateGroup) */
|
||||
UPDATE TBL_ACTION_GRP SET
|
||||
GRP_NM = #{name}
|
||||
, DSCRP = #{description}
|
||||
WHERE GRP_ID = #{id}</update>
|
||||
|
||||
<delete id="removeGroups" parameterType="map">/* 기능그룹 삭제(actionGroupMapper.removeGroups) */
|
||||
DELETE FROM TBL_ACTION_GRP
|
||||
WHERE GRP_ID IN (<foreach collection="groupIDs" item="groupID" separator=",">#{groupID}</foreach>)</delete>
|
||||
|
||||
<select id="getActionList" parameterType="map" resultType="dataobject">/* 그룹별 기능 가져오기(actionGroupMapper.getActionList) */
|
||||
SELECT *
|
||||
FROM TBL_GRP_ACTION
|
||||
<if test="groupIDs != null">WHERE GRP_ID IN (<foreach collection="groupIDs" item="groupID" separator=",">#{groupID}</foreach>)</if>
|
||||
ORDER BY GRP_ID, ACTION
|
||||
</select>
|
||||
|
||||
<insert id="addActions" parameterType="map">/* 그룹별 기능 추가(actionGroupMapper.addActions) */
|
||||
INSERT INTO TBL_GRP_ACTION (GRP_ID, ACTION, INS_DT)
|
||||
SELECT GRP_ID, ACTION, CURRENT_TIMESTAMP()
|
||||
FROM (<foreach collection="actions" item="action" separator="UNION">
|
||||
SELECT #{groupID} GRP_ID, #{action} ACTION FROM DUAL</foreach>
|
||||
) A
|
||||
WHERE NOT EXISTS (
|
||||
SELECT GRP_ID, ACTION
|
||||
FROM TBL_GRP_ACTION B
|
||||
WHERE B.GRP_ID = A.GRP_ID
|
||||
AND B.ACTION = A.ACTION
|
||||
)</insert>
|
||||
|
||||
<delete id="removeActions" parameterType="map">/* 그룹별 기능 삭제(actionGroupMapper.removeActions) */
|
||||
DELETE FROM TBL_GRP_ACTION
|
||||
<where>
|
||||
<if test="groupIDs != null">AND GRP_ID IN (<foreach collection="groupIDs" item="groupID" separator=",">#{groupID}</foreach>)</if>
|
||||
<if test="actions != null">AND ACTION IN (<foreach collection="actions" item="action" separator=",">#{action}</foreach>)</if>
|
||||
</where>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,69 @@
|
||||
<?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">
|
||||
<mapper namespace="authentication">
|
||||
|
||||
<resultMap id="policyRow" type="cokr.xit.base.security.authentication.AuthenticationPolicy">
|
||||
<result property="userID" column="USER_ID"/>
|
||||
<result property="ipAddress" column="IP_ADRS"/>
|
||||
<result property="duplicateYN" column="DPLCT_YN"/>
|
||||
<result property="limitYN" column="LIMIT_YN"/>
|
||||
<result property="createdBy" column="INS_ID"/>
|
||||
<result property="createdAt" column="INS_DT"/>
|
||||
<result property="modifiedBy" column="UPD_ID"/>
|
||||
<result property="lastModified" column="UPD_DT"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="getPolicyList" parameterType="map" resultType="dataobject">/* 로그인 정책 목록 조회(authentication.getPolicyList) */
|
||||
<include refid="utility.paging-prefix"/>
|
||||
SELECT A.USER_ID
|
||||
, USER_NM
|
||||
, IP_ADRS
|
||||
, DPLCT_YN
|
||||
, LIMIT_YN
|
||||
, UPD_ID
|
||||
, UPD_DT
|
||||
FROM TBL_USER A LEFT OUTER JOIN TBL_LOGIN_POLICY B ON A.USER_ID = B.USER_ID
|
||||
<if test="term != null">WHERE A.${by} LIKE CONCAT('%', #{term}, '%')</if>
|
||||
<include refid="utility.paging-suffix"/></select>
|
||||
|
||||
<select id="getPolicies" parameterType="map" resultMap="policyRow">/* 로그인 정책 가져오기(authentication.getPolicies) */
|
||||
SELECT *
|
||||
FROM TBL_LOGIN_POLICY
|
||||
<if test="userIDs != null">WHERE USER_ID IN (<foreach collection="userIDs" item="userID" separator=",">#{userID}</foreach>)</if>
|
||||
ORDER BY USER_ID</select>
|
||||
|
||||
<insert id="insertPolicy" parameterType="map">/* 로그인 정책 등록(authentication.insertPolicy) */
|
||||
INSERT INTO TBL_LOGIN_POLICY (
|
||||
USER_ID
|
||||
, IP_ADRS
|
||||
, DPLCT_YN
|
||||
, LIMIT_YN
|
||||
, FRST_REGISTER_ID
|
||||
, FRST_REGIST_PNTTM
|
||||
, UPD_ID
|
||||
, UPD_DT
|
||||
) VALUES (
|
||||
#{policy.userID}
|
||||
, #{policy.ipAddress}
|
||||
, #{policy.duplicateYN}
|
||||
, #{policy.limitYN}
|
||||
, #{currentUser.id}
|
||||
, CURRENT_TIMESTAMP()
|
||||
, #{currentUser.id}
|
||||
, CURRENT_TIMESTAMP()
|
||||
)</insert>
|
||||
|
||||
<update id="updatePolicy" parameterType="map">/* 로그인 정책 수정(authentication.updatePolicy) */
|
||||
UPDATE TBL_LOGIN_POLICY SET
|
||||
IP_ADRS = #{policy.ipAddress}
|
||||
, DPLCT_YN = #{policy.duplicateYN}
|
||||
, LIMIT_YN = #{policy.limitYN}
|
||||
, UPD_ID = #{currentUser.id}
|
||||
, UPD_DT = CURRENT_TIMESTAMP()
|
||||
WHERE USER_ID = #{policy.userID}</update>
|
||||
|
||||
<delete id="removePolicy" parameterType="map">/* 로그인 정책 삭제(authentication.removePolicy) */
|
||||
DELETE FROM TBL_LOGIN_POLICY
|
||||
WHERE USER_ID IN (<foreach collection="userIDs" item="userID" separator=",">#{userID}</foreach>)</delete>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,141 @@
|
||||
<?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">
|
||||
<mapper namespace="cokr.xit.base.security.access.dao.AuthorityMapper">
|
||||
|
||||
<resultMap id="authRow" type="cokr.xit.base.security.Authority">
|
||||
<result property="type" column="AUTH_TYPE"/>
|
||||
<result property="id" column="AUTH_ID"/>
|
||||
<result property="name" column="AUTH_NM"/>
|
||||
<result property="infoScope" column="INF_SCP"/>
|
||||
<result property="userInfoScope" column="USER_INF_SCP"/>
|
||||
<result property="description" column="DSCRP"/>
|
||||
<result property="createdAt" column="INS_DT"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectAuthorities"><include refid="utility.paging-prefix" />
|
||||
SELECT * FROM (
|
||||
SELECT 0 AUTH_TYPE, 'ROLE_ADMIN' AUTH_ID, '시스템 관리자' AUTH_NM, '시스템 관리자' DSCRP, 'all' INF_SCP, 'all' USER_INF_SCP, CURRENT_TIMESTAMP() NOW UNION
|
||||
SELECT 1 AUTH_TYPE, 'ROLE_ANONYMOUS' AUTH_ID, '익명 사용자' AUTH_NM, '모든 사용자' DSCRP, 'none' INF_SCP, 'none' USER_INF_SCP, CURRENT_TIMESTAMP() NOW UNION
|
||||
SELECT 1 AUTH_TYPE, 'ROLE_USER' AUTH_ID, '시스템 사용자' AUTH_NM, '로그인한 사용자' DSCRP, 'self' INF_SCP, 'self' USER_INF_SCP, CURRENT_TIMESTAMP() NOW UNION
|
||||
SELECT 2 AUTH_TYPE, AUTH_ID, AUTH_NM, DSCRP, INF_SCP, USER_INF_SCP, INS_DT
|
||||
FROM TBL_AUTHORITY
|
||||
) A
|
||||
<where>
|
||||
<if test="authIDs != null">AND AUTH_ID IN (<foreach collection="authIDs" item="authID" separator=",">#{authID}</foreach>)</if>
|
||||
<if test="by != null and term != null">AND ${by} LIKE CONCAT('%', #{term}, '%')</if>
|
||||
</where>
|
||||
<include refid="utility.orderBy"/>
|
||||
<include refid="utility.paging-suffix" /></sql>
|
||||
|
||||
<select id="getAuthorityList" parameterType="map" resultType="dataobject">/* 권한 목록 조회(authorityMapper.getAuthorityList) */
|
||||
<include refid="selectAuthorities" /></select>
|
||||
|
||||
<select id="getAuthorities" parameterType="map" resultMap="authRow">/* 권한 가져오기(authorityMapper.getAuthorities) */
|
||||
<include refid="selectAuthorities" /></select>
|
||||
|
||||
<insert id="insertAuthority" parameterType="cokr.xit.base.security.Authority">/* 권한 등록(authorityMapper.insertAuthority) */
|
||||
INSERT INTO TBL_AUTHORITY (
|
||||
AUTH_ID
|
||||
, AUTH_NM
|
||||
, DSCRP
|
||||
, INF_SCP
|
||||
, USER_INF_SCP
|
||||
, INS_DT
|
||||
) VALUES (
|
||||
#{id}
|
||||
, #{name}
|
||||
, #{description}
|
||||
, #{infoScope}
|
||||
, #{userInfoScope}
|
||||
, CURRENT_TIMESTAMP()
|
||||
)</insert>
|
||||
|
||||
<update id="updateAuthority" parameterType="cokr.xit.base.security.Authority">/* 권한 수정(authorityMapper.updateAuthority) */
|
||||
UPDATE TBL_AUTHORITY SET
|
||||
AUTH_NM = #{name}
|
||||
, DSCRP = #{description}
|
||||
, INF_SCP = #{infoScope}
|
||||
, USER_INF_SCP = #{userInfoScope}
|
||||
WHERE AUTH_ID = #{id}</update>
|
||||
|
||||
<delete id="removeAuthorities" parameterType="map">/* 권한 삭제(authorityMapper.removeAuthorities) */
|
||||
DELETE FROM TBL_AUTHORITY
|
||||
WHERE AUTH_ID IN (<foreach collection="authIDs" item="authID" separator=",">#{authID}</foreach>)</delete>
|
||||
|
||||
<select id="getActionGroupList" parameterType="map" resultType="dataobject">/* 권한-기능그룹 가져오기(authorityMapper.getActionGroups) */
|
||||
<include refid="utility.paging-prefix" />
|
||||
SELECT *
|
||||
FROM TBL_AUTH_ACTION
|
||||
<if test="authIDs != null">WHERE AUTH_ID IN (<foreach collection="authIDs" item="authID" separator=",">#{authID}</foreach>)</if>
|
||||
ORDER BY AUTH_ID, GRP_ID
|
||||
<include refid="utility.paging-suffix" /></select>
|
||||
|
||||
<insert id="addActionGroups" parameterType="map">/* 권한-기능그룹 추가(authorityMapper.addActionGroups) */
|
||||
INSERT INTO TBL_AUTH_ACTION (AUTH_ID, GRP_ID, INS_DT)
|
||||
SELECT AUTH_ID, GRP_ID, CURRENT_TIMESTAMP()
|
||||
FROM (<foreach collection="groupIDs" item="groupID" separator=" UNION">
|
||||
SELECT #{authID} AUTH_ID, #{groupID} GRP_ID FROM DUAL</foreach>
|
||||
) A
|
||||
WHERE NOT EXISTS (
|
||||
SELECT AUTH_ID, GRP_ID
|
||||
FROM TBL_AUTH_ACTION B
|
||||
WHERE B.AUTH_ID = A.AUTH_ID
|
||||
AND B.GRP_ID = A.GRP_ID
|
||||
)</insert>
|
||||
|
||||
<delete id="removeActionGroups" parameterType="map">/* 권한-기능그룹 삭제(authorityMapper.removeActionGroups) */
|
||||
DELETE FROM TBL_AUTH_ACTION
|
||||
<where>
|
||||
<if test="authIDs != null">AND AUTH_ID IN (<foreach collection="authIDs" item="authID" separator=",">#{authID}</foreach>)</if>
|
||||
<if test="groupIDs != null">AND GRP_ID IN (<foreach collection="groupIDs" item="groupID" separator=",">#{groupID}</foreach>)</if>
|
||||
</where>
|
||||
</delete>
|
||||
|
||||
<select id="getActionList" resultType="dataobject">/* 권한-기능 가져오기(authorityMapper.getActionList) */
|
||||
SELECT A.AUTH_ID
|
||||
, A.GRP_ID
|
||||
, C.ACTION
|
||||
FROM TBL_AUTH_ACTION A
|
||||
, TBL_ACTION_GRP B
|
||||
, TBL_GRP_ACTION C
|
||||
WHERE A.GRP_ID = B.GRP_ID
|
||||
AND B.GRP_ID = C.GRP_ID
|
||||
ORDER BY A.AUTH_ID, A.GRP_ID, C.ACTION</select>
|
||||
|
||||
<sql id="selectAuthUser">
|
||||
<include refid="utility.paging-prefix" />
|
||||
SELECT *
|
||||
FROM TBL_AUTH_USER
|
||||
<if test="authIDs != null">WHERE AUTH_ID IN (<foreach collection="authIDs" item="authID" separator=",">#{authID}</foreach>)</if>
|
||||
<if test="userIDs != null">WHERE USER_ID IN (<foreach collection="userIDs" item="userID" separator=",">#{userID}</foreach>)</if>
|
||||
<include refid="utility.orderBy"/>
|
||||
<include refid="utility.paging-suffix" /></sql>
|
||||
|
||||
<select id="getUserList" parameterType="map" resultType="dataobject">/* 권한-사용자 가져오기(authorityMapper.getUserList) */
|
||||
<include refid="selectAuthUser" /></select>
|
||||
|
||||
<select id="getUserAuths" parameterType="map" resultType="dataobject">/* 사용자-권한 가져오기(authorityMapper.getUserAuths) */
|
||||
<include refid="selectAuthUser" /></select>
|
||||
|
||||
<insert id="addUsers" parameterType="map">/* 권한-사용자 추가(authorityMapper.addUsers) */
|
||||
INSERT INTO TBL_AUTH_USER (AUTH_ID, USER_ID, INS_DT)
|
||||
SELECT AUTH_ID, USER_ID, CURRENT_TIMESTAMP()
|
||||
FROM (<foreach collection="userIDs" item="userID" separator="UNION">
|
||||
SELECT #{authID} AUTH_ID, #{userID} USER_ID FROM DUAL</foreach>
|
||||
) A
|
||||
WHERE NOT EXISTS (
|
||||
SELECT AUTH_ID, USER_ID
|
||||
FROM TBL_AUTH_USER B
|
||||
WHERE B.AUTH_ID = A.AUTH_ID
|
||||
AND B.USER_ID = A.USER_ID
|
||||
)</insert>
|
||||
|
||||
<delete id="removeUsers" parameterType="map">/* 권한-사용자 삭제(authorityMapper.removeUsers) */
|
||||
DELETE FROM TBL_AUTH_USER
|
||||
<where>
|
||||
<if test="authIDs != null">AND AUTH_ID IN (<foreach collection="authIDs" item="authID" separator=",">#{authID}</foreach>)</if>
|
||||
<if test="userIDs != null">AND USER_ID IN (<foreach collection="userIDs" item="userID" separator=",">#{userID}</foreach>)</if>
|
||||
</where>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,14 @@
|
||||
<?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">
|
||||
<mapper namespace="test">
|
||||
|
||||
<insert id="insert" parameterType="map">${sql}</insert>
|
||||
|
||||
<update id="update" parameterType="map">${sql}</update>
|
||||
|
||||
<delete id="delete" parameterType="map">${sql}</delete>
|
||||
|
||||
<update id="commit">COMMIT</update>
|
||||
|
||||
|
||||
</mapper>
|
@ -0,0 +1,189 @@
|
||||
<?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">
|
||||
<!-- 업무 사용자 -->
|
||||
<mapper namespace="cokr.xit.base.user.dao.UserMapper">
|
||||
|
||||
<resultMap id="userRow" type="cokr.xit.base.user.ManagedUser">
|
||||
<result property="id" column="USER_ID"/>
|
||||
<result property="key" column="USER_KEY"/>
|
||||
<result property="name" column="USER_NM"/>
|
||||
<result property="password" column="PASSWD"/>
|
||||
<result property="passwordHint" column="PASSWD_HINT"/>
|
||||
<result property="passwordHintAnswer" column="PASSWD_NSR"/>
|
||||
<result property="empNo" column="EMP_NO"/>
|
||||
<result property="residentRegNo" column="RSDNT_NO"/>
|
||||
<result property="gender" column="GENDER"/>
|
||||
<result property="birthday" column="BIRTHDAY"/>
|
||||
<result property="areaNo" column="AREA_NO"/>
|
||||
<result property="zipCode" column="ZIP_CODE"/>
|
||||
<result property="address" column="ADRS"/>
|
||||
<result property="addressDetail" column="ADRS_DTL"/>
|
||||
<result property="phoneNo" column="PHN_NO"/>
|
||||
<result property="mobilePhoneNo" column="MBL_PHN_NO"/>
|
||||
<result property="faxNo" column="FX_NO"/>
|
||||
<result property="emailAddress" column="EML_ADRS"/>
|
||||
<result property="positionName" column="POS_NM"/>
|
||||
<result property="groupID" column="GRP_ID"/>
|
||||
<result property="orgID" column="ORG_ID"/>
|
||||
<result property="institute" column="NSTT_CD"/>
|
||||
<result property="certificateDn" column="CRTFC_DN"/>
|
||||
<result property="locked" column="LOCK_YN"/>
|
||||
<result property="lockCount" column="LOCK_CNT"/>
|
||||
<result property="lockedDate" column="LOCK_DT"/>
|
||||
<result property="registeredDate" column="INS_DT"/>
|
||||
<result property="status" column="STATUS"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectUsers"><include refid="utility.paging-prefix" />
|
||||
SELECT USER_ID
|
||||
, USER_KEY
|
||||
, USER_NM
|
||||
<if test='password == true'> , PASSWD</if>
|
||||
, PASSWD_HINT
|
||||
, PASSWD_NSR
|
||||
, EMP_NO
|
||||
, RSDNT_NO
|
||||
, GENDER
|
||||
, BIRTHDAY
|
||||
, AREA_NO
|
||||
, ZIP_CODE
|
||||
, ADRS
|
||||
, ADRS_DTL
|
||||
, PHN_NO
|
||||
, MBL_PHN_NO
|
||||
, FX_NO
|
||||
, EML_ADRS
|
||||
, POS_NM
|
||||
, GRP_ID
|
||||
, ORG_ID
|
||||
, NSTT_CD
|
||||
, CRTFC_DN
|
||||
, LOCK_YN
|
||||
, LOCK_CNT
|
||||
, LOCK_DT
|
||||
, INS_DT
|
||||
, STATUS
|
||||
FROM TBL_USER
|
||||
<where><if test="by != null and term != null">AND ${by} LIKE CONCAT('%', #{term}, '%')</if>
|
||||
<if test="userIDs != null">USER_ID IN (<foreach collection="userIDs" item="userID" separator=",">#{userID}</foreach>)</if>
|
||||
<if test="userIDs == null and status == null">AND STATUS != 'D'</if>
|
||||
<if test="status != null">AND STATUS = #{status}</if></where>
|
||||
<include refid="utility.paging-suffix" /></sql>
|
||||
|
||||
<select id="getUserList" parameterType="map" resultType="dataobject">/* 사용자 목록 조회(userMapper.getUserList) */
|
||||
<include refid="selectUsers"/></select>
|
||||
|
||||
<select id="getUsers" parameterType="map" resultMap="userRow">/* 사용자 가져오기(userMapper.getUsers) */
|
||||
<include refid="selectUsers"/></select>
|
||||
|
||||
<insert id="insertUser" parameterType="cokr.xit.base.user.ManagedUser">/* 사용자 정보 등록(userMapper.insertUser) */
|
||||
INSERT INTO TBL_USER (
|
||||
USER_ID
|
||||
, USER_KEY
|
||||
, USER_NM
|
||||
, PASSWD
|
||||
, PASSWD_HINT
|
||||
, PASSWD_NSR
|
||||
, EMP_NO
|
||||
, RSDNT_NO
|
||||
, GENDER
|
||||
, BIRTHDAY
|
||||
, AREA_NO
|
||||
, ZIP_CODE
|
||||
, ADRS
|
||||
, ADRS_DTL
|
||||
, PHN_NO
|
||||
, MBL_PHN_NO
|
||||
, FX_NO
|
||||
, EML_ADRS
|
||||
, POS_NM
|
||||
, GRP_ID
|
||||
, ORG_ID
|
||||
, NSTT_CD
|
||||
, CRTFC_DN
|
||||
, LOCK_YN
|
||||
, LOCK_CNT
|
||||
, LOCK_DT
|
||||
, INS_DT
|
||||
, STATUS
|
||||
) VALUES (
|
||||
#{id}
|
||||
, #{key}
|
||||
, #{name}
|
||||
, #{password}
|
||||
, #{passwordHint}
|
||||
, #{passwordHintAnswer}
|
||||
, #{empNo}
|
||||
, #{residentRegNo}
|
||||
, #{gender}
|
||||
, #{birthday}
|
||||
, #{areaNo}
|
||||
, #{zipCode}
|
||||
, #{address}
|
||||
, #{addressDetail}
|
||||
, #{phoneNo}
|
||||
, #{mobilePhoneNo}
|
||||
, #{faxNo}
|
||||
, #{emailAddress}
|
||||
, #{positionName}
|
||||
, #{groupID}
|
||||
, #{orgID}
|
||||
, #{institute}
|
||||
, #{certificateDn}
|
||||
, 'N'
|
||||
, 0
|
||||
, NULL
|
||||
, CURRENT_TIMESTAMP()
|
||||
, #{status}
|
||||
)</insert>
|
||||
|
||||
<update id="updateUser" parameterType="cokr.xit.base.user.ManagedUser">/* 사용자 정보 수정(userMapper.updateUser) */
|
||||
UPDATE TBL_USER SET
|
||||
USER_KEY = #{key}
|
||||
, USER_NM = #{name}
|
||||
, PASSWD_HINT = #{passwordHint}
|
||||
, PASSWD_NSR = #{passwordHintAnswer}
|
||||
, EMP_NO = #{empNo}
|
||||
, RSDNT_NO = #{residentRegNo}
|
||||
, GENDER = #{gender}
|
||||
, BIRTHDAY = #{birthday}
|
||||
, AREA_NO = #{areaNo}
|
||||
, ZIP_CODE = #{zipCode}
|
||||
, ADRS = #{address}
|
||||
, ADRS_DTL = #{addressDetail}
|
||||
, PHN_NO = #{phoneNo}
|
||||
, MBL_PHN_NO = #{mobilePhoneNo}
|
||||
, FX_NO = #{faxNo}
|
||||
, EML_ADRS = #{emailAddress}
|
||||
, POS_NM = #{positionName}
|
||||
, GRP_ID = #{groupID}
|
||||
, ORG_ID = #{orgID}
|
||||
, NSTT_CD = #{institute}
|
||||
, CRTFC_DN = #{certificateDn}
|
||||
WHERE USER_ID = #{id}</update>
|
||||
|
||||
<update id="changePassword" parameterType="map">/* 비밀번호 변경(userMapper.changePassword) */
|
||||
UPDATE TBL_USER SET PASSWD = CASE USER_ID
|
||||
<foreach collection="userPasswords" item="userPassword" separator=" ">WHEN #{userPassword.userID} THEN #{userPassword.password}</foreach>
|
||||
ELSE PASSWD END
|
||||
WHERE USER_ID IN (<foreach collection="userIDs" item="userID" separator=",">#{userID}</foreach>)
|
||||
</update>
|
||||
|
||||
<update id="lockUsers" parameterType="map">/* 사용자 잠김 해제(userMapper.lockUsers) */
|
||||
UPDATE TBL_USER SET
|
||||
<if test='lock == true'> LOCK_YN = 'Y'
|
||||
, LOCK_CNT = LOCK_CNT + 1
|
||||
, LOCK_DT = CURRENT_TIMESTAMP()</if>
|
||||
<if test='lock == false'> LOCK_YN = 'N'
|
||||
, LOCK_CNT = 0
|
||||
, LOCK_DT = NULL</if>
|
||||
WHERE USER_ID IN (<foreach collection="userIDs" item="userID" separator=",">#{userID}</foreach>)
|
||||
</update>
|
||||
|
||||
<update id="setStatus" parameterType="map">/* 사용자 상태 변경(userMapper.setStatus) */
|
||||
UPDATE TBL_USER SET STATUS = #{status}
|
||||
WHERE USER_ID IN (<foreach collection="userIDs" item="userID" separator=",">#{userID}</foreach>)
|
||||
AND STATUS != #{status}
|
||||
</update>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,27 @@
|
||||
<?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">
|
||||
<mapper namespace="utility">
|
||||
|
||||
<!-- For Maria DB -->
|
||||
<sql id="paging-prefix"><if test="fetchSize != null and fetchSize > 0">
|
||||
SELECT QROWS.* FROM (
|
||||
SELECT ROW_NUMBER() OVER(<include refid="utility.sortBy" />) ROW_NUM
|
||||
, COUNT(*) OVER() TOT_CNT, QBODY.*
|
||||
FROM (</if></sql>
|
||||
|
||||
<sql id="paging-suffix"><if test="fetchSize != null and fetchSize > 0"> ) QBODY
|
||||
) QROWS
|
||||
WHERE ROW_NUM BETWEEN ((#{pageNum} - 1) * #{fetchSize}) + 1 AND (#{pageNum} * #{fetchSize})</if></sql>
|
||||
|
||||
<select id="foundRows" resultType="dataobject">/* 전체 결과수 가져오기(utility.foundRows) */
|
||||
SELECT FOUND_ROWS() TOT_CNT</select>
|
||||
|
||||
<sql id="sortBy"><if test="orderBy != null and orderBy != ''">ORDER BY ${orderBy}</if></sql>
|
||||
|
||||
<sql id="orderBy"><if test="fetchSize == null or fetchSize < 1"><include refid="utility.sortBy" /></if></sql>
|
||||
|
||||
<sql id="thisDay">IFNULL(#{thisDay}, TO_CHAR(CURRENT_DATE, 'YYYYMMDD'))</sql>
|
||||
|
||||
<sql id="selectThisDay">SELECT<include refid="utility.thisDay" />THIS_DAY</sql>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||
<configuration>
|
||||
|
||||
<settings>
|
||||
<setting name="mapUnderscoreToCamelCase" value="false"/>
|
||||
<setting name="cacheEnabled" value="false" />
|
||||
<setting name="jdbcTypeForNull" value="NULL" />
|
||||
<setting name="callSettersOnNulls" value="true"/>
|
||||
</settings>
|
||||
|
||||
<typeAliases>
|
||||
<typeAlias alias="egovMap" type="org.egovframe.rte.psl.dataaccess.util.EgovMap"/>
|
||||
<typeAlias alias="dataobject" type="cokr.xit.foundation.data.DataObject"/>
|
||||
</typeAliases>
|
||||
|
||||
<typeHandlers>
|
||||
<typeHandler handler="cokr.xit.foundation.data.RowValueHandler" javaType="java.lang.Object"/>
|
||||
</typeHandlers>
|
||||
|
||||
<plugins>
|
||||
<plugin interceptor="cokr.xit.foundation.data.paging.PagingSupport" />
|
||||
</plugins>
|
||||
|
||||
</configuration>
|
Loading…
Reference in New Issue