로그인 성공 처리
: 로그인을 성공한 후에 로그인 이력 로그를 기록하는 등의 동작을 하고 싶은 경우 사용함
security-context.xml
<security:form-login login-page="/login"/>를 수정
<!-- 사용자가 정의한 로그인 페이지의 URI를 지정함
사용자 정의 로그인 성공 처리자를 지정함 -->
<security:form-login login-page="/login"
authentication-success-handler-ref="customLoginSuccess"/>
<beans/> 안에 추가함
<bean id="customLoginSuccess" class="kr.or.ddit.security.CustomLoginSuccessHandler"></bean>
CustomLoginSuccessHandler.java
package kr.or.ddit.security;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import lombok.extern.slf4j.Slf4j;
/* /notice/register -> loginForm -> 로그인 -> CustomLoginSuccessHandler(성공)
-> 사용자 작업.. -> /notice/register 로 리다이렉트 해줌
(스프링 시큐리티에서 기본적으로 사용되는 구현 클래스)
*/
@Slf4j
public class CustomLoginSuccessHandler extends
SavedRequestAwareAuthenticationSuccessHandler{ //로그인 성공 핸들러를 상속 받음
//부모 클래스의 메소드를 재정의
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication auth) throws ServletException, IOException {
log.info("onAuthenticationSuccess 왔다");
//auth.getPrincipal() : 사용자 정보를 가져옴 (정해진 이름을 써줘야지만 값을 가져올 수 있음)
//시큐리티에서 사용자 정보는 User 클래스의 객체로 저장됨(CustomUser.java를 참고)
User costomUser = (User)auth.getPrincipal();
//사용자의 아이디를 리턴 받기
log.info("username : " + costomUser.getUsername());
//auth.getAuthorities() -> 권한들(ROLE_MEMBER,ROLE_ADMIN)
//authority.getAuthority() : ROLE_MEMBER
List<String> roleNames = new ArrayList<String>();
auth.getAuthorities().forEach(authority->{
roleNames.add(authority.getAuthority());
});
log.info("roleNames : " + roleNames);
//부모에게 줌
super.onAuthenticationSuccess(request, response, auth);
}
}
로그아웃 처리
security-context.xml
</security:http> 안에 추가
<!-- 로그아웃 처리를 위한 URI를 지정하고, 로그아웃한 후에 세션을 무효화(session.invalidate())함
/logout : post방식 요청URI -> form의 action="/logout"에서 사용 -->
<security:logout logout-url="/logout" invalidate-session="true" />
aside.jsp
추가
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
변경
<!-- Sidebar -->
<div class="sidebar">
<!-- Sidebar user panel (optional) -->
<!-- /// 로그인 안함 시작 /// -->
<!-- isAnonymous() 는 로그인 안 했을 때 true -> 아래 코드 실행 -->
<sec:authorize access="isAnonymous()"> <!-- 인가 : 권한 -->
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
<div class="image">
<img src="/resources/adminlte/dist/img/user2-160x160.jpg"
class="img-circle elevation-2" alt="User Image">
</div>
<div class="info">
<a href="#" class="d-block">Alexander Pierce</a>
</div>
</div>
</sec:authorize>
<!-- /// 로그인 안함 끝 /// -->
<!-- /// 로그인 함 시작 /// -->
<sec:authorize access="isAuthenticated()">
<!-- principal : 사용자정보 객체 -->
<%-- <sec:authentication property="principal"/> --%>
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
<div class="image">
<img src="/resources/upload/mang6.jpg"
class="img-circle elevation-2" alt="User Image">
</div>
<div class="info">
<a href="#" class="d-block">개똥이님 환영합니다.</a>
<form action="/logout" method="post"> <!-- 꼭 post여야함 -->
<button type="submit" class="btn btn-block btn-secondary btn-xs">로그아웃</button>
<sec:csrfInput/>
</form>
</div>
</div>
</sec:authorize>
<!-- /// 로그인 함 끝 /// -->
JDBC 이용한 인증/인가 처리
테이블 생성
CREATE TABLE USERS(
USERNAME VARCHAR2(150),
PASSWORD VARCHAR2(150),
ENABLED VARCHAR2(1),
CONSTRAINT PK_USERS PRIMARY KEY(USERNAME)
);
CREATE TABLE AUTHORITIES(
USERNAME VARCHAR2(150),
AUTHORITY VARCHAR2(150),
CONSTRAINT PK_AUTH PRIMARY KEY(USERNAME, AUTHORITY),
CONSTRAINT FK_AUTH FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME) -- 다른 테이블을 참조함
);
데이터 삽입
기존 테이블에 데이터가 없는 경우 일일히 데이터를 넣는 걸 추천함
INSERT INTO USERS(USERNAME,PASSWORD)
SELECT EMP_NO, 'java' FROM EMPLOYEE;
COMMIT;
INSERT INTO AUTHORITIES(USERNAME,AUTHORITY)
SELECT EMP_NO, 'ROLE_MEMBER' FROM EMPLOYEE;
COMMIT;
데이터 잘 들어갔는지 확인
SELECT A.USERNAME, A.PASSWORD, A.ENABLED
, B.USERNAME, B.AUTHORITY
FROM USERS A, AUTHORITIES B
WHERE A.USERNAME = B.USERNAME;
추후 ADMIN 도 테스트하기 위해 데이터를 변경해놓아야함

security-context.xml
</security:authentication-provider> 안에 있는 것 수정
<!-- jdbc로 해야 db에 있는 걸로 가져올 수 있음 -->
<!-- root-context.xml에 있음 -->
<security:jdbc-user-service data-source-ref="dataSource"/>
<!-- 비밀번호 암호화 -->
<security:password-encoder ref="passwordEncoder"/>
<!-- <security:user-service> 사용자 설정 -->
<!-- <security:user name="member" password="{noop}1234" authorities="ROLE_MEMBER"/> -->
<!-- <security:user name="admin" password="{noop}1234" authorities="ROLE_MEMBER,ROLE_ADMIN"/> -->
<!-- </security:user-service> -->
</beans> 안에 추가
<!-- 비밀번호 암호화 처리글 -->
<bean id="passwordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>
LoginController.java
package kr.or.ddit.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
public class LoginController {
//DI / IoC
//passwordEncoder 객체는 security-context.xml의 bean에 등록되어 있음
@Autowired
PasswordEncoder passwordEncoder;
@GetMapping("/login")
public String loginForm(Model model) {
String pwd = "java";
String encodedPwd = this.passwordEncoder.encode(pwd);
log.info("encodedPwd : " + encodedPwd);
//forwarding : jsp
// /views/ + loginForm + ".jsp";
return "loginForm";
}
}
데이터 삽입
INSERT INTO EMPLOYEE_AUTH(EMP_NO, AUTH)
SELECT EMP_NO, 'ROLE_MEMBER'
FROM EMPLOYEE;
COMMIT;
+ 하나의 데이터만 ROLE_ADMIN으로 수정해야함
security-context.xml
<security:authentication-manager> 변경
<security:authentication-manager>
<!-- 지정된 아이디와 패스워드로 로그인이 가능하도록 설정함 -->
<security:authentication-provider user-service-ref="customUserDetailsService"> <!-- 인증 제공자 -->
<!-- 비밀번호 암호화 -->
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</beans> 안에 추가
<bean id="customUserDetailsService" class="kr.or.ddit.security.CustomUserDetailsService">
</bean>
CustomUserDetailsService.java
package kr.or.ddit.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import kr.or.ddit.mapper.EmployeeMapper;
import kr.or.ddit.vo.EmployeeVO;
import lombok.extern.slf4j.Slf4j;
/*
UserDetailsService : 스프링 시큐리티에서 제공해주고 있는
사용자 상세 정보를 갖고 있는 인터페이스
*/
@Slf4j
@Service
public class CustomUserDetailsService implements UserDetailsService {
//EMPLOYEE 테이블을 위한 매퍼 인터페이스
//DI(Dependency Injection) : 의존성 주입
//IoC(Inversion of Control) : 제어의 역전
@Autowired
private EmployeeMapper employeeMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//1) 사용자 정보를 검색
//username : 로그인 시 입력 받은 회원의 아이디. <input type="text" name="username"
log.info("CustomUserDetailsService->username : " + username);
//1명이 로그인을 함
EmployeeVO employeeVO = this.employeeMapper.detail(username);
log.info("CustomUserDetailsService->employeeVO : " + employeeVO);
//MVC에서는 Controller로 리턴하지 않고, CustomUser로 리턴함
//CustomUser : 사용자 정의 유저 정보. extends User를 상속받고 있음
//2) 스프링 시큐리티의 User 객체의 정보로 넣어줌 => 프링이가 이제부터 해당 유저를 관리
//User : 스프링 시큐리에서 제공해주는 사용자 정보 클래스
/*
memberVO(우리) -> user(시큐리티)
-----------------
empNo -> username
empPwd -> password
enabled -> enabled
employeeAuthVOList -> authorities
*/
return employeeVO==null?null:new CustomUser(employeeVO);
}
}
EmployeeMapper.java
package kr.or.ddit.security;
import kr.or.ddit.vo.EmployeeVO;
public interface EmployeeMapper {
public EmployeeVO detail(String username);
}
employee2_SQL.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.EmployeeMapper">
<resultMap type="employeeVO" id="employeeMap">
<result property="empNo" column="EMP_NO"/>
<result property="empName" column="EMP_NAME"/>
<result property="empAddress" column="EMP_ADDRESS"/>
<result property="empTelno" column="EMP_TELNO"/>
<result property="empSalary" column="EMP_SALARY"/>
<result property="filename" column="FILENAME"/>
<result property="empPwd" column="EMP_PWD"/>
<result property="enabled" column="ENABLED"/>
<collection property="employeeAuthVOList" resultMap="employeeAuthMap"></collection>
</resultMap>
<resultMap type="employeeAuthVO" id="employeeAuthMap">
<result property="empNo" column="EMP_NO"/>
<result property="auth" column="AUTH"/>
</resultMap>
<select id="detail" parameterType="String" resultMap="employeeMap">
SELECT A.EMP_NO, A.EMP_NAME, A.EMP_ADDRESS, A.EMP_TELNO, A.EMP_SALARY, A.FILENAME, A.EMP_PWD, A.ENABLED
, B.EMP_NO, B.AUTH
FROM EMPLOYEE A, EMPLOYEE_AUTH B
WHERE A.EMP_NO = B.EMP_NO
AND A.EMP_NO = #{username}
</select>
</mapper>
EmployeeVO.java
package kr.or.ddit.vo;
import java.util.List;
import javax.validation.Valid;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.multipart.MultipartFile;
import lombok.Data;
@Data
public class EmployeeVO {
@NotBlank(message = "직원 번호를 입력해주세요")
private String empNo;
@NotBlank(message = "직원 명을 입력해주세요")
private String empName;
@NotBlank(message = "주소를 입력해주세요")
private String empAddress;
@NotBlank(message = "연락처를 입력해주세요")
private String empTelno;
@Range(min=1,message="급여를 입력해주세요.")
private int empSalary;
private String filename;
private String empPwd;
private String enabled;
@Valid
private List<LicenseVO> licenseVOList;
//중첩된 자바빈 컬렉션
private List<EmployeeAuthVO> employeeAuthVOList;
//EMPLOYEE : 증명사진 = 1 : 1
private MultipartFile uploadFile;
}
EmployeeAuthVO.java
package kr.or.ddit.vo;
import lombok.Data;
@Data
public class EmployeeAuthVO {
private String empNo;
private String auth;
}
mybatisAlias.xml
</typeAliases> 안에 추가
<typeAlias type="kr.or.ddit.vo.EmployeeAuthVO" alias="employeeAuthVO"/>
CustomUser.java
package kr.or.ddit.security;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import kr.or.ddit.vo.EmployeeVO;
//User : 스프링 시큐리티의 사용자 정보를 관리하는 사용자 최상위 클래스
public class CustomUser extends User {
/* User 클래스의 프로퍼티
private String password;
private final String username;
private final Set<GrantedAuthority> authorities;
private final boolean accountNonExpired;
private final boolean accountNonLocked;
private final boolean credentialsNonExpired;
private final boolean enabled;
*/
private EmployeeVO employeeVO;
//User의 생성자를 처리해줌
public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public CustomUser(EmployeeVO employeeVO) {
//사용자가 정의한 (select한) MemberVO 타입의 객체 memberVO를
//스프링 시큐리티에서 제공해주고 있는 UsersDetails 타입으로 변환
//회원정보를 보내줄테니 이제부터 프링이 너가 관리해줘
super(employeeVO.getEmpNo(),employeeVO.getEmpPwd(),
employeeVO.getEmployeeAuthVOList().stream() //stream : 쭉 나열
.map(auth->new SimpleGrantedAuthority(auth.getAuth())) //객체 2개가 생성됨
.collect(Collectors.toList())
);
this.employeeVO = employeeVO;
}
public EmployeeVO getEmployeeVO() {
return employeeVO;
}
public void setEmployeeVO(EmployeeVO employeeVO) {
this.employeeVO = employeeVO;
}
}
테이블 정보


데이터 삽입
INSERT INTO MEMBER_AUTH(USER_ID,AUTH)
SELECT USER_ID,'ROLE_MEMBER'
FROM MEMBER;
COMMIT;
SELECT * FROM MEMBER_AUTH;

SELECT A.USER_ID, A.USER_NAME, A.PASSWORD, A.REG_DATE, A.COIN, A.ENABLED
, B.AUTH
FROM MEMBER A, MEMBER_AUTH B
WHERE A.USER_ID = B.USER_ID
AND A.USER_ID = 'b001';

security-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- CustomAccessDeniedHandler customAccessDenied = new CustomAccessDeniedHandler(); 와 같은 문장임 -->
<bean id="customAccessDenied"
class="kr.or.ddit.security.CustomAccessDeniedHandler"></bean>
<bean id="customLoginSuccess" class="kr.or.ddit.security.CustomLoginSuccessHandler"></bean>
<!-- 비밀번호 암호화 처리글 -->
<bean id="passwordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>
<!-- 스프링 시큐리티의 UserDetailsService를 구현한 클래스를 빈으로 등록함 -->
<bean id="customUserDetailsService2" class="kr.or.ddit.security.CustomUserDetailsService2">
</bean>
<security:http>
<!-- URI 패턴으로 접근 제한을 설정함 -->
<!-- URL을 가로챔 -->
<!-- 누구나 접근 가능 -> 생략 가능 -->
<security:intercept-url pattern="/board/list" access="permitAll"/> <!-- permitAll : 누구나 접근 가능 -->
<security:intercept-url pattern="/board/register" access="hasRole('ROLE_MEMBER')" /> <!-- ROLE_MEMBER 권한을 가졌을 때 : 회원만 접근 -->
<security:intercept-url pattern="/notice/list" access="permitAll" />
<security:intercept-url pattern="/notice/register" access="hasRole('ROLE_ADMIN')" /> <!-- ROLE_ADMIN 권한을 가졌을 때 : 관리자만 접근 -->
<!-- 사용자가 정의한 로그인 페이지의 URI를 지정함
사용자 정의 로그인 성공 처리자를 지정함
/login : get방식 -> LoginController에서 매핑 -->
<security:form-login login-page="/login"
authentication-success-handler-ref="customLoginSuccess"/>
<!-- 등록한 사용자 정의 bean을 접근 거부 처리자로 지정함 -->
<security:access-denied-handler ref="customAccessDenied"/>
<!-- 로그아웃 처리를 위한 URI를 지정하고, 로그아웃한 후에 세션을 무효화(session.invalidate())함
/logout : post방식 요청URI -> form의 action="/logout"에서 사용 -->
<security:logout logout-url="/logout" invalidate-session="true" />
</security:http>
<security:authentication-manager>
<!-- 지정된 아이디와 패스워드로 로그인이 가능하도록 설정함 -->
<security:authentication-provider user-service-ref="customUserDetailsService2"> <!-- 인증 제공자 -->
<!-- 비밀번호 암호화 -->
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
CustomUserDetailsService2.java
package kr.or.ddit.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import kr.or.ddit.mapper.MemberMapper;
import kr.or.ddit.vo.Member;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class CustomUserDetailsService2 implements UserDetailsService {
@Autowired
private MemberMapper memberMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("CustomUserDetailsService2 -> username : " + username);
//select
Member member = this.memberMapper.detail(username);
log.info("CustomUserDetailsService2->member : " + member);
//User(스프링꺼)
//CustomUser2(우리꺼)
return member==null?null:new CustomUser2(member);
}
}
MemberMapper.java
root-context에 Mapper 인터페이스 설정을 미리 해둠
package kr.or.ddit.mapper;
import kr.or.ddit.vo.Member;
public interface MemberMapper {
public Member detail(String username);
}
member2_SQL.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.MemberMapper">
<resultMap type="member" id="memberMap">
<result property="userId" column="USER_ID"/>
<result property="userName" column="USER_NAME"/>
<result property="password" column="PASSWORD"/>
<result property="regDate" column="REG_DATE"/>
<result property="coin" column="COIN"/>
<result property="enabled" column="ENABLED"/>
<collection property="memberAuthVOList" resultMap="memberAuthMap"></collection>
</resultMap>
<resultMap type="memberAuthVO" id="memberAuthMap">
<result property="userId" column="USER_ID"/>
<result property="auth" column="AUTH"/>
</resultMap>
<!-- 부모(MEMBER) 1 : 자식(MEMBER_AUTH) N = 1 : N -->
<select id="detail" parameterType="String" resultMap="memberMap">
SELECT A.USER_ID, A.USER_NAME, A.PASSWORD, A.REG_DATE, A.COIN, A.ENABLED
, B.AUTH
FROM MEMBER A, MEMBER_AUTH B
WHERE A.USER_ID = B.USER_ID
AND A.USER_ID = #{username}
</select>
</mapper>
Member.java
package kr.or.ddit.vo;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.multipart.MultipartFile;
import lombok.Data;
@Data
public class Member {
@NotBlank
private String userId;
@NotBlank(message="사용자명을 입력해주세요.")
@Size(max=3, message="최대 3글자까지만 작성해주세요.")
private String userName;
private String password = "1234";
@DateTimeFormat(pattern="yyyy-MM-dd") private Date regDate;
private int coin;
private String enabled;
//부모(MEMBER) 1 : 자식(MEMBER_AUTH) N = 1 : N
private List<MemberAuthVO> memberAuthVOList;
}
MemberAuthVO.java
package kr.or.ddit.vo;
import lombok.Data;
@Data
public class MemberAuthVO {
private String userId;
private String auth;
}
mybatisAlias.xml
<typeAliases> 안에 추가
<typeAlias type="kr.or.ddit.vo.MemberAuthVO" alias="memberAuthVO"/>
CustomUser2.java
package kr.or.ddit.security;
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import kr.or.ddit.vo.Member;
//사용자가 유저를 정의함
//memberVO(select결과)정보를 User(스프링 시큐리티에서 정의된 유저) 객체 정보에 연계하여 넣어줌
//CustomUser의 객체 = principal
public class CustomUser2 extends User {
private Member member;
public CustomUser2(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
//return member==null?null:new CumstomUser2(member);
public CustomUser2(Member member) {
super(member.getUserId(), member.getPassword(),
member.getMemberAuthVOList().stream()
.map(auth->new SimpleGrantedAuthority(auth.getAuth()))
.collect(Collectors.toList())
);
this.member = member;
}
public Member getMember() {
return member;
}
public void setMember(Member member) {
this.member = member;
}
}


- 이름 변경 (principal)
aside.jsp
principal 추가 및 설정 관련 수정
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
<!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-primary elevation-4">
<!-- Brand Logo -->
<a href="index3.html" class="brand-link"> <img
src="/resources/adminlte/dist/img/AdminLTELogo.png"
alt="AdminLTE Logo" class="brand-image img-circle elevation-3"
style="opacity: .8"> <span class="brand-text font-weight-light">AdminLTE
3</span>
</a>
<!-- Sidebar -->
<div class="sidebar">
<!-- Sidebar user panel (optional) -->
<!-- /// 로그인 안함 시작 /// -->
<!-- isAnonymous() 는 로그인 안 했을 때 true -> 아래 코드 실행 -->
<sec:authorize access="isAnonymous()"> <!-- 인가 : 권한 -->
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
<div class="image">
<img src="/resources/adminlte/dist/img/user2-160x160.jpg"
class="img-circle elevation-2" alt="User Image">
</div>
<div class="info">
<a href="#" class="d-block">Alexander Pierce</a>
</div>
</div>
</sec:authorize>
<!-- /// 로그인 안함 끝 /// -->
<!-- /// 로그인 함 시작 /// -->
<sec:authorize access="isAuthenticated()">
<!-- principal : 사용자정보 객체
var속성이 있으면 JSTL변수에 할당.
var속성이 없으면 화면에 출력.-->
<sec:authentication property="principal.member" var="member"/>
<sec:authentication property="principal.member.memberAuthVOList" var="memberAuthVOList" />
<c:forEach var="memberAuthVO" items="${memberAuthVOList}" varStatus="stat">
<p>${memberAuthVO.auth}</p>
</c:forEach>
<div class="user-panel mt-3 pb-3 mb-3 d-flex">
<div class="image">
<img src="/resources/upload/mang6.jpg"
class="img-circle elevation-2" alt="User Image">
</div>
<div class="info">
<a href="#" class="d-block">${member.userName}님 환영합니다.</a>
<form action="/logout" method="post"> <!-- 꼭 post여야함 -->
<button type="submit" class="btn btn-block btn-secondary btn-xs">로그아웃</button>
<sec:csrfInput/>
</form>
</div>
</div>
</sec:authorize>
<!-- /// 로그인 함 끝 /// -->
<!-- SidebarSearch Form -->
<div class="form-inline">
<div class="input-group" data-widget="sidebar-search">
<input class="form-control form-control-sidebar" type="search"
placeholder="Search" aria-label="Search">
<div class="input-group-append">
<button class="btn btn-sidebar">
<i class="fas fa-search fa-fw"></i>
</button>
</div>
</div>
</div>
<!-- Sidebar Menu -->
<nav class="mt-2">
<ul class="nav nav-pills nav-sidebar flex-column"
data-widget="treeview" role="menu" data-accordion="false">
<!-- Add icons to the links using the .nav-icon class
with font-awesome or any other icon font library -->
<li class="nav-item menu-open"><a href="#"
class="nav-link active"> <i
class="nav-icon fas fa-tachometer-alt"></i>
<p>
Dashboard <i class="right fas fa-angle-left"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="./index.html"
class="nav-link active"> <i class="far fa-circle nav-icon"></i>
<p>Dashboard v1</p>
</a></li>
<li class="nav-item"><a href="./index2.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Dashboard v2</p>
</a></li>
<li class="nav-item"><a href="./index3.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Dashboard v3</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="pages/widgets.html"
class="nav-link"> <i class="nav-icon fas fa-th"></i>
<p>
Widgets <span class="right badge badge-danger">New</span>
</p>
</a></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon fas fa-copy"></i>
<p>
Layout Options <i class="fas fa-angle-left right"></i> <span
class="badge badge-info right">6</span>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/layout/top-nav.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Top Navigation</p>
</a></li>
<li class="nav-item"><a
href="pages/layout/top-nav-sidebar.html" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>Top Navigation + Sidebar</p>
</a></li>
<li class="nav-item"><a href="pages/layout/boxed.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Boxed</p>
</a></li>
<li class="nav-item"><a
href="pages/layout/fixed-sidebar.html" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>Fixed Sidebar</p>
</a></li>
<li class="nav-item"><a
href="pages/layout/fixed-sidebar-custom.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>
Fixed Sidebar <small>+ Custom Area</small>
</p>
</a></li>
<li class="nav-item"><a href="pages/layout/fixed-topnav.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Fixed Navbar</p>
</a></li>
<li class="nav-item"><a href="pages/layout/fixed-footer.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Fixed Footer</p>
</a></li>
<li class="nav-item"><a
href="pages/layout/collapsed-sidebar.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Collapsed Sidebar</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon fas fa-chart-pie"></i>
<p>
Charts <i class="right fas fa-angle-left"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/charts/chartjs.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>ChartJS</p>
</a></li>
<li class="nav-item"><a href="pages/charts/flot.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Flot</p>
</a></li>
<li class="nav-item"><a href="pages/charts/inline.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Inline</p>
</a></li>
<li class="nav-item"><a href="pages/charts/uplot.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>uPlot</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon fas fa-tree"></i>
<p>
UI Elements <i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/UI/general.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>General</p>
</a></li>
<li class="nav-item"><a href="pages/UI/icons.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Icons</p>
</a></li>
<li class="nav-item"><a href="pages/UI/buttons.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Buttons</p>
</a></li>
<li class="nav-item"><a href="pages/UI/sliders.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Sliders</p>
</a></li>
<li class="nav-item"><a href="pages/UI/modals.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Modals & Alerts</p>
</a></li>
<li class="nav-item"><a href="pages/UI/navbar.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Navbar & Tabs</p>
</a></li>
<li class="nav-item"><a href="pages/UI/timeline.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Timeline</p>
</a></li>
<li class="nav-item"><a href="pages/UI/ribbons.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Ribbons</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon fas fa-edit"></i>
<p>
Forms <i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/forms/general.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>General Elements</p>
</a></li>
<li class="nav-item"><a href="pages/forms/advanced.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Advanced Elements</p>
</a></li>
<li class="nav-item"><a href="pages/forms/editors.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Editors</p>
</a></li>
<li class="nav-item"><a href="pages/forms/validation.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Validation</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon fas fa-table"></i>
<p>
Tables <i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/tables/simple.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Simple Tables</p>
</a></li>
<li class="nav-item"><a href="pages/tables/data.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>DataTables</p>
</a></li>
<li class="nav-item"><a href="pages/tables/jsgrid.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>jsGrid</p>
</a></li>
</ul></li>
<li class="nav-header">EXAMPLES</li>
<li class="nav-item"><a href="pages/calendar.html"
class="nav-link"> <i class="nav-icon far fa-calendar-alt"></i>
<p>
Calendar <span class="badge badge-info right">2</span>
</p>
</a></li>
<li class="nav-item"><a href="pages/gallery.html"
class="nav-link"> <i class="nav-icon far fa-image"></i>
<p>Gallery</p>
</a></li>
<li class="nav-item"><a href="pages/kanban.html"
class="nav-link"> <i class="nav-icon fas fa-columns"></i>
<p>Kanban Board</p>
</a></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon far fa-envelope"></i>
<p>
Mailbox <i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/mailbox/mailbox.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Inbox</p>
</a></li>
<li class="nav-item"><a href="pages/mailbox/compose.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Compose</p>
</a></li>
<li class="nav-item"><a href="pages/mailbox/read-mail.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Read</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon fas fa-book"></i>
<p>
Pages <i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/examples/invoice.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Invoice</p>
</a></li>
<li class="nav-item"><a href="pages/examples/profile.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Profile</p>
</a></li>
<li class="nav-item"><a href="pages/examples/e-commerce.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>E-commerce</p>
</a></li>
<li class="nav-item"><a href="pages/examples/projects.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Projects</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/project-add.html" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>Project Add</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/project-edit.html" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>Project Edit</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/project-detail.html" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>Project Detail</p>
</a></li>
<li class="nav-item"><a href="pages/examples/contacts.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Contacts</p>
</a></li>
<li class="nav-item"><a href="pages/examples/faq.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>FAQ</p>
</a></li>
<li class="nav-item"><a href="pages/examples/contact-us.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Contact us</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon far fa-plus-square"></i>
<p>
Extras <i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="#" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>
Login & Register v1 <i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/examples/login.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Login v1</p>
</a></li>
<li class="nav-item"><a href="pages/examples/register.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Register v1</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/forgot-password.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Forgot Password v1</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/recover-password.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Recover Password v1</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>
Login & Register v2 <i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/examples/login-v2.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Login v2</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/register-v2.html" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>Register v2</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/forgot-password-v2.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Forgot Password v2</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/recover-password-v2.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Recover Password v2</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="pages/examples/lockscreen.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Lockscreen</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/legacy-user-menu.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Legacy User Menu</p>
</a></li>
<li class="nav-item"><a
href="pages/examples/language-menu.html" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>Language Menu</p>
</a></li>
<li class="nav-item"><a href="pages/examples/404.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Error 404</p>
</a></li>
<li class="nav-item"><a href="pages/examples/500.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Error 500</p>
</a></li>
<li class="nav-item"><a href="pages/examples/pace.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Pace</p>
</a></li>
<li class="nav-item"><a href="pages/examples/blank.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Blank Page</p>
</a></li>
<li class="nav-item"><a href="starter.html" class="nav-link">
<i class="far fa-circle nav-icon"></i>
<p>Starter Page</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon fas fa-search"></i>
<p>
Search <i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="pages/search/simple.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Simple Search</p>
</a></li>
<li class="nav-item"><a href="pages/search/enhanced.html"
class="nav-link"> <i class="far fa-circle nav-icon"></i>
<p>Enhanced</p>
</a></li>
</ul></li>
<li class="nav-header">MISCELLANEOUS</li>
<li class="nav-item"><a href="iframe.html" class="nav-link">
<i class="nav-icon fas fa-ellipsis-h"></i>
<p>Tabbed IFrame Plugin</p>
</a></li>
<li class="nav-item"><a href="https://adminlte.io/docs/3.1/"
class="nav-link"> <i class="nav-icon fas fa-file"></i>
<p>Documentation</p>
</a></li>
<li class="nav-header">MULTI LEVEL EXAMPLE</li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="fas fa-circle nav-icon"></i>
<p>Level 1</p>
</a></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon fas fa-circle"></i>
<p>
Level 1 <i class="right fas fa-angle-left"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="#" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>Level 2</p>
</a></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>
Level 2 <i class="right fas fa-angle-left"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item"><a href="#" class="nav-link"> <i
class="far fa-dot-circle nav-icon"></i>
<p>Level 3</p>
</a></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="far fa-dot-circle nav-icon"></i>
<p>Level 3</p>
</a></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="far fa-dot-circle nav-icon"></i>
<p>Level 3</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="far fa-circle nav-icon"></i>
<p>Level 2</p>
</a></li>
</ul></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="fas fa-circle nav-icon"></i>
<p>Level 1</p>
</a></li>
<li class="nav-header">LABELS</li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon far fa-circle text-danger"></i>
<p class="text">Important</p>
</a></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon far fa-circle text-warning"></i>
<p>Warning</p>
</a></li>
<li class="nav-item"><a href="#" class="nav-link"> <i
class="nav-icon far fa-circle text-info"></i>
<p>Informational</p>
</a></li>
</ul>
</nav>
<!-- /.sidebar-menu -->
</div>
<!-- /.sidebar -->
</aside>
'스프링 프레임워크' 카테고리의 다른 글
[스프링 프레임워크] 30장 다음 우편번호, 주소 가져오기, 계층형 구조 (0) | 2024.05.20 |
---|---|
[스프링 프레임워크] 29장 자동 로그인, 스프링 시큐리티 애너테이션 (1) | 2024.05.20 |
[스프링 프레임워크] 27장 스프링 시큐리티1 (0) | 2024.05.16 |
[스프링 프레임워크] 26장 트랙잭션, 예외처리 (0) | 2024.05.16 |
[스프링 프레임워크] 25장 AOP (0) | 2024.05.16 |