시큐리티 사용하기 위한 라이브러리 추강
pom.xml
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.8.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>5.8.6</version>
</dependency>
ojdbc8 23.2.0.0 버젼 jdk1.8에 security상에서 password를 인식하지 못하는 상황발생!~~ㅠㅠ
<!-- ojdbc8
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>23.2.0.0</version>
</dependency>
-->
<!-- https://mvnrepository.com/artifact/com.oracle.ojdbc/ojdbc8 -->
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
시큐리티 설정파일 맹글기!(기본 개념 잘 잡깅!)
security-context.xml
<security:http auto-config="true">
<security:intercept-url pattern="/oho/all"
access="permitAll" />
<security:intercept-url pattern="/oho/member"
access="hasRole('ROLE_MEMBER')" />
<security:form-login />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="roze" password="myroze"
authorities="ROLE_MEMBER" />
<security:user name="admin" password="myroze"
authorities="ROLE_MEMBER,ROLE_ADMIN" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
위 설정파일 읽어들이깅!
root-context.xml
<import resource="security-context.xml" />
시큐리티가 동작하기 위해서 필터체인이 동작해야 함!(시큐리티 필터체인 등록)
web.xml
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
조금씩 조금씩 다가가깅
시큐리티 태그 라이브러링
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
csrf 넣깅
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<sec:csrfInput/>
AccessDeniedHandler
AuthenticationSuccessHandler
spring security 설명에 보통 나오는 sql문
--drop table USERS;
create table users(
username varchar2(50) not null primary key,
password varchar2(50) not null,
enabled char(1) DEFAULT '1'
);
--drop TABLE authorities;
create table authorities(
username VARCHAR2(50) not null,
authority VARCHAR2(50) not null,
CONSTRAINT fk_username FOREIGN key(username) REFERENCES users(username)
);
--drop index index_username_authority;
create UNIQUE index index_username_authority on authorities(username,authority);
위에서는 name하고 id하고 헷깔리니 아래 처럼 쪼메 수정
drop table USERS;
create table users(
userid varchar2(50) not null primary key,
username varchar2(50) not null,
password varchar2(60) not null,
enabled char(1) DEFAULT '1',
regdate date default sysdate
);
drop TABLE authorities;
create table authorities(
userid VARCHAR2(50) not null,
authority VARCHAR2(50) not null,
CONSTRAINT fk_username FOREIGN key(userid) REFERENCES users(userid)
);
drop index index_username_authority;
create UNIQUE index index_username_authority on authorities(userid,authority);
권한VO
@Setter
@Getter
@ToString
public class AuthVO {
private String userid;
private String auth;
}
멤버VO
@Getter
@Setter
@ToString
public class MemberVO {
private String userid;
private String userpw;
private String username;
private boolean enabled;
private Date regdate;
private List<AuthVO> authList;
}
Member맵퍼
@Mapper
public interface MemberMapper {
public int insertMember(MemberVO member);
public int insertAuth(AuthVO auth);
public MemberVO read(String userid);
}
Mybatis Mapper.xml(SQL)
<?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="com.e7e.sec.mapper.MemberMapper">
<resultMap type="MemberVO" id="memberMap">
<id property="userid" column="userid"/>
<result property="userid" column="userid"/>
<result property="userpw" column="password"/>
<result property="username" column="username"/>
<result property="regdate" column="regdate"/>
<collection property="authList" resultMap="authMap" />
</resultMap>
<resultMap type="AuthVO" id="authMap">
<result property="userid" column="userid"/>
<result property="auth" column="authority"/>
</resultMap>
<select id="read" resultMap="memberMap" parameterType="string">
select
mem.userid, password, username, enabled, regdate, authority
from users mem , authorities auth
where mem.userid = #{userid} and mem.userid = auth.userid
</select>
<insert id="insertMember" parameterType="MemberVO">
insert into users(userid,username,password) values(#{userid},#{username},#{userpw})
</insert>
<insert id="insertAuth" parameterType="AuthVO">
insert into authorities (userid, authority) values(#{userid},#{auth})
</insert>
</mapper>
@Slf4j
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:config/spring/root-context.xml")
public class MemberTest {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private MemberMapper memberMapper;
@Test
@DisplayName("UserRegister")
@Disabled
public void insertUsers() {
MemberVO member = new MemberVO();
for(int i=1; i<=10; i++) {
member.setUserid("jinsu" + i);
member.setUsername("niceJinsu"+i);
member.setUserpw(passwordEncoder.encode("jinsu"+i));
assertEquals(1,memberMapper.insertMember(member));
}
}
@Test
@DisplayName("AuthRegister")
@Disabled
public void insertAuth() {
AuthVO auth = new AuthVO();
for(int i=1; i<=10; i++) {
auth.setUserid("jinsu" + i);
auth.setAuth("ROLE_USER");
assertEquals(1,memberMapper.insertAuth(auth));
}
}
@Test
@DisplayName("Select User")
public void readUser() {
MemberVO member = memberMapper.read("jinsu1");
log.debug("check {}",member);
member.getAuthList().forEach(authVO -> log.debug("{}",authVO));
}
}
@Slf4j
public class CustomAccessDeniedHandler implements AccessDeniedHandler{
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
//개발 중에는 필히 에러를 확인해야 함!
log.debug("Denied Reason:" + accessDeniedException.getMessage());
}
}
@Slf4j
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse res,
Authentication auth) throws IOException, ServletException {
log.info("auth success");
Iterator<? extends GrantedAuthority> authIter= auth.getAuthorities().iterator();
while(authIter.hasNext()) {
System.out.println(authIter.next());
}
res.sendRedirect("/e7e/sample2/admin");
}
}
@Slf4j
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private MemberMapper memberMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("ckk{}"+username);
MemberVO memberVO = memberMapper.read(username);
if(memberVO != null) {
return new CustomUser(memberVO);
}else {
throw new UsernameNotFoundException(username);
}
}
}
@Getter
public class CustomUser extends User {
private static final long serialVersionUID = 1L;
private MemberVO member;
public CustomUser(String username, String password,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public CustomUser(MemberVO vo) {
super(vo.getUserid(), vo.getUserpw(),
vo.getAuthList().stream().map(auth -> new SimpleGrantedAuthority(auth.getAuth())).collect(Collectors.toList()));
this.member = vo;
}
}
security taglibs 확인
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>ADMIN</h1>
<p><sec:authentication property="principal"/></p>
<p><sec:authentication property="principal.member"/></p>
<p><sec:authentication property="principal.member.username"/></p>
<p><sec:authentication property="principal.username" var="merong"/></p>
<p><sec:authentication property="principal.member.authList" var="myAuths"/></p>
<h1>${merong }</h1>
<h1>${myAuths}</h1>
</body>
</html>
remember-me 체크박스를 사용하기 위해 필요한 테이블
create table persistent_logins (
username varchar2(64) not null,
series varchar2(64) primary key,
token varchar2(64) not null,
last_used timestamp not null
)
<?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-5.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<bean id="customUserDetailsService" class="or.pe.e7e.security.CustomUserDetailsService"/>
<bean id="customLoginSuccessHandler" class="or.pe.e7e.security.CustomLoginSuccessHandler"/>
<bean id="customAccessDeniedHandler" class="com.e7e.sec.security.CustomAccessDeniedHandler"/>
<security:http >
<security:headers>
<security:frame-options policy="SAMEORIGIN"/>
<security:xss-protection />
<security:content-security-policy policy-directives="scriptsrc: 'self'" />
</security:headers>
<security:access-denied-handler ref="customAccessDeniedHandler" />
<security:intercept-url pattern="/aaa/test" access="hasRole('ROLE_ADMIN')"/>
<security:form-login authentication-success-handler-ref="customLoginSuccessHandler" />
<security:logout logout-url="/logout" invalidate-session="true" />
<security:csrf disabled="false"/>
<security:session-management>
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
</security:session-management>
<security:remember-me />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="bcryptPasswordEncoder"/>
<!-- <security:user-service>
<security:user name="roze" password="$2a$10$T2zgQO4yiA0hKczi60HwFOFhAldFgVgUrOJk1awAEpVgd.fn6Um/." authorities="ROLE_MEMBER"/>
</security:user-service>
--> </security:authentication-provider>
</security:authentication-manager>
</beans>
멀티설정 참공
<?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">
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<security:http pattern="/member/**" authentication-manager-ref="member">
<security:headers>
<security:frame-options policy="DENY"/>
</security:headers>
<security:intercept-url pattern="/member/ccc" access="hasRole('MEMBER')" />
<security:form-login login-page="/member/bbb" login-processing-url="/member/login" />
<security:logout logout-url="/member/logout" logout-success-url="/member/bbb"/>
</security:http>
<security:http pattern="/merong/**" authentication-manager-ref="merong">
<security:headers>
<security:frame-options policy="DENY"/>
</security:headers>
<security:intercept-url pattern="/merong/ccc" access="hasRole('MEMBER')" />
<security:form-login login-page="/merong/bbb" login-processing-url="/merong/login" />
<security:logout logout-url="/merong/logout" logout-success-url="/" />
</security:http>
<security:http auto-config="true" pattern="/**" authentication-manager-ref="all">
<security:headers>
<security:frame-options policy="DENY"/>
</security:headers>
<security:intercept-url pattern="/**" access="hasRole('MEMBER')" />
</security:http>
<security:authentication-manager id="member" >
<security:authentication-provider >
<security:password-encoder ref="passwordEncoder"/>
<security:user-service >
<security:user name="aiyou" password="$2a$10$xUmubWRg0X/BXPrgCbBADOVcqH.849Q7n.TtDIaDJaxXDVW5d1v/a" authorities="ROLE_MEMBER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<security:authentication-manager id="merong" >
<security:authentication-provider>
<security:password-encoder ref="passwordEncoder"/>
<security:user-service>
<security:user name="jieun" password="$2a$10$T7kAac9bON42pF4FAEgLB./QHDNHs.av1lnvnG1cr.dkVyujD3GFi" authorities="ROLE_MEMBER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<security:authentication-manager id="all" >
<security:authentication-provider>
<security:password-encoder ref="passwordEncoder"/>
<security:user-service>
<security:user name="test" password="$2a$10$T7kAac9bON42pF4FAEgLB./QHDNHs.av1lnvnG1cr.dkVyujD3GFi" authorities="ROLE_MEMBER"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
매뉴얼 로그인 설정
@Slf4j
@Controller
public class MloginController {
//@Resource(name = "authenticationManager")
@Autowired
private AuthenticationManager authenticationManager;
@GetMapping("/anmerong")
public String mLogin(HttpServletRequest req) {
//Autowired 잘 되었는지? 확인(D.I)
log.debug("check:"+authenticationManager);
//DB에 존재하는 아이디/암호여야 함!, 안 그럼 없는 사용자!
UsernamePasswordAuthenticationToken myAuth =
new UsernamePasswordAuthenticationToken("jinsu1", "jinsu1");
Authentication auth = authenticationManager.authenticate(myAuth);
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(auth);
//Session이 없으면 생성
HttpSession session = req.getSession(true);
//Session에 시큐리티 컨텍스트 등록
//org.springframework.security.web.context.HttpSessionSecurityContextRepository.class에
// "SPRING_SECURITY_CONTEXT_KEY" 이 정의 되어 있음. 그냥 참고망
session.setAttribute("SPRING_SECURITY_CONTEXT_KEY", sc);
return "home";
}
주의 AuthenticationManager Autowired 하기 위해서 설정파일에서 id값 주는 거 안 빼먹깅!
<security:authentication-manager id="authenticationManager">
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="passwordEncoder"/>
<!-- <security:user-service>
<security:user name="test" password="$2a$10$T7kAac9bON42pF4FAEgLB./QHDNHs.av1lnvnG1cr.dkVyujD3GFi" authorities="ROLE_MEMBER"/>
</security:user-service> -->
</security:authentication-provider>
</security:authentication-manager>
https://www.youtube.com/watch?v=kKSzvq4Ip08
SQL로그 남기기(log4jdbc-log4j2) (4) | 2022.05.10 |
---|---|
작은 재미 오픈API (7) | 2022.05.10 |
Filter(필터) 인터셉터와 구분해 주세요 (3) | 2022.05.04 |
스케줄러(Scheduler,Quartz포함) (0) | 2022.05.04 |
인터셉터(가로채깅) (1) | 2022.05.03 |