이번에 작업해볼것은 스프링 시큐리티를 이용한 로그인 을해볼려고합니다.
화면단은 타임리프이용할것입니다.
이번에 사용되는권한은
ROLE_MEMBER 권한과 ROLE_ADMIN 권한
관리자와 사용자의 멤버가 존재합니다.
간단하게
메인페이지, 로그인 페이지가있고
권한마다 버튼이 다르게보이는 예제입니다.
비로그인(손님) - 로그인 버튼,회원가입 버튼, 메뉴 목록 버튼
로그인(MEMBER권한) - 로그아웃, 메뉴 목록 버튼, 주문 버튼
로그인(ADMIN권한) - 로그아웃, 메뉴 목록 버튼, 주문 버튼, 관리자 페이지 버튼
이렇게나뉩니다.
상세로 이동하는 기능은 추가하지 않았습니다.
우선 html파일입니다.
main.html
타임리프를 이용해 작업하였고,
sec:authorize = "isAuthenticated()" << 권한이 있는 사용자만보이는 블럭
sec:authorize= "isAnonymouse()" << 비로그인 사용자만 보이는 블럭
sec:authorize= "hasRole("Member")" << 권한이 MEMBER인 사람만 보이는 블럭
sec:authorize= "hasRole("ADMIN")" << 권한이 ADMIN인 사람만 보이는 블럭
으로 jsp처럼 if문이라고 생각하면 편할것ㄱ같다.
<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org"
xmlns:sec="http://thymeleaf.org/extras/spring-security"
>
<head>
<meta charset="UTF-8">
<title>main</title>
</head>
<body>
<h1 align="center">main 페이지 입니다.</h1>
<th:block sec:authorize="isAuthenticated()">
<div align="right">
<!-- 스프링 시큐리티가 제공하는 Principal 객체는 담겨있는것이
아이디, 패스워드, 권한 3가지만 담겨있다 만약 다른 정보들도 같이담고싶으면 개인적으로 커스텀 마이징해야한다! -->
<h2><span sec:authentication="Principal.username"></span>님 환영합니다!</h2>
<h2><span sec:authentication="Principal.memberNo"></span>님 환영합니다!</h2>
<button onclick="location.href='/member/logout'">로그아웃</button>
</div>
</th:block>
<!-- 권한이 없는 사용자 일시 -->
<th:block sec:authorize="isAnonymous()">
<div align="right">
<h3>로그인이 필요한 서비스입니다.</h3>
<button onclick="location.href='/member/login'">로그인</button>
<button>회원가입</button>
</div>
</th:block>
<div align="left">
<!-- 모든 사용자가 볼수있는 메뉴 -->
<button>메뉴보기</button>
<!-- 아래까지가 회원이 볼수있는 메뉴 -->
<th:block sec:authorize="hasRole('MEMBER')">
<button>주문하기</button>
</th:block>
<!-- 아래까지가 관리자가 볼수있는 메뉴 -->
<th:block sec:authorize="hasRole('ADMIN')">
<button>관리자 메뉴</button>
</th:block>
</div>
</body>
</html>
login.html
로그인 페이지 작성시 주의사항으로는
아이디 비밀번호 name값을 스프링 시큐리티에서 정해준값으로 지정해줘야한다.
id = username
password = password
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<div align="center">
<h1>로그인</h1>
<form action="/member/login" method="post">
<!-- 여기서 아이디와 비밀번호의 name값은 스프링 시큐리티가 정해준 값이다 다르게하면 안됨! -->
아이디 : <input type="text" name="username"> <br>
비밀번호 : <input type="password" name="password"><br><br>
<button type="submit">로그인</button>
</form>
</div>
</body>
</html>
화면에서 아이디 비밀번호 입력후 로그인버튼을누르게 되면
전에 작성했던 스프링 시큐리티 설정 파일의해 실행된다.
로그인페이지로 요청하면서
ServiceImpl 클래스의 아래의 메소드를 호출한다.
하지만 전과 다른점은 User객체를 기존 것을사용하지않고 여러정보를담은 UserImpl 클래스로 새로생성하여 커스텀마이징하였다.
커스텀마이징을 하지않은 상태에서 사용시 담아있는 정보는 아이디, 비밀번호, 권한만 담아져있어서 사용하기 쉽지가않았다.
UserImpl.java
기존의 Member 필드값들을 전부다 가져왔고 User 객체는 필수로 상속 해야한다
그리고 필수 생성자를 생성후
setDetails 메소드에 값들을 세팅한다.
여기서 중요한점은 나중에 값을 읽을때필요한 getter 메소드는 필수도있어야한다.
package com.memory.security.member.model.vo;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
public class UserImpl extends User{
private int memberNo;
private String memberId;
private String memberPwd;
private String tempPwnYn;
private Date pwdChangedDatetime;
private String pwdExpDate;
private String memberName;
private Date memberRegistDatetime;
private int accumLoginCount;
private int loginFailedCount;
private String accLockYn;
private String accInactiveYn;
private String accExpDate;
private String accExpYn;
private Date accSecessionDatetime;
private String accSecessionYn;
private List<MemberRole> memberRoleList;
// User객체 상속후 필수 구현 생성자
public UserImpl(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
// User객체 커스텀 마이징할 메소드
public void setDetails(Member member) {
// 필드값 전부 세팅
this.memberNo = member.getMemberNo();
this.memberId = member.getMemberId();
this.memberPwd = member.getMemberPwd();
this.tempPwnYn = member.getTempPwnYn();
this.pwdChangedDatetime = member.getPwdChangedDatetime();
this.pwdExpDate = member.getPwdExpDate();
this.memberName = member.getMemberName();
this.memberRegistDatetime = member.getMemberRegistDatetime();
this.accumLoginCount = member.getAccumLoginCount();
this.loginFailedCount = member.getLoginFailedCount();
this.accLockYn = member.getAccLockYn();
this.accInactiveYn = member.getAccInactiveYn();
this.accExpDate = member.getAccExpDate();
this.accExpYn = member.getAccExpYn();
this.accSecessionDatetime = member.getAccSecessionDatetime();
this.accSecessionYn = member.getAccSecessionYn();
this.memberRoleList = member.getMemberRoleList();
}
// getter 메소드는 필수도있어야 함
// 이유는 시큐리티에서 값을 읽을때 사용함!
public int getMemberNo() {
return memberNo;
}
public String getMemberId() {
return memberId;
}
public String getMemberPwd() {
return memberPwd;
}
public String getTempPwnYn() {
return tempPwnYn;
}
public Date getPwdChangedDatetime() {
return pwdChangedDatetime;
}
public String getPwdExpDate() {
return pwdExpDate;
}
public String getMemberName() {
return memberName;
}
public Date getMemberRegistDatetime() {
return memberRegistDatetime;
}
public int getAccumLoginCount() {
return accumLoginCount;
}
public int getLoginFailedCount() {
return loginFailedCount;
}
public String getAccLockYn() {
return accLockYn;
}
public String getAccInactiveYn() {
return accInactiveYn;
}
public String getAccExpDate() {
return accExpDate;
}
public String getAccExpYn() {
return accExpYn;
}
public Date getAccSecessionDatetime() {
return accSecessionDatetime;
}
public String getAccSecessionYn() {
return accSecessionYn;
}
public List<MemberRole> getMemberRoleList() {
return memberRoleList;
}
}
그리고
로그인 상태에서 로그아웃버튼을누르면
이것도 전에 설정해뒀떤 스프링 시큐리티 설정파일에서 작동하여 동작이된다.
'프로그래밍 > SpringBoot' 카테고리의 다른 글
SpringBoot - 빈 프로젝트 버전별 압축파일 (0) | 2023.09.16 |
---|---|
SpringBoot - 5. 스프링 시큐리티 (2) | 2021.11.08 |
SpringBoot - 4. 메뉴 조회, 추가 실습(타임리프 사용) (0) | 2021.11.04 |
SpringBoot - 3. SpringBoot 프로젝트 생성 (0) | 2021.11.01 |
SpringBoot - 2. STS4 설치하기 (0) | 2021.11.01 |