참고
이거 만들어줘야함
Spring Bean Configuration생성
security-context로 name지어주고 피니쉬
Namespaces에서 security선택 후 저장 하고
다시 security-context로 돌아오면
이거 쓸 수 있음
pom.xml
검색해보면 버전이 23.2.0.0 최신버전이다 하지만 이것을 쓴다면
뭔가 안맞음 무튼 그래서 버전 다운해줘야함
아래 코드 복사해서
<!-- 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: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>
sccurity-context.xml에 붙여넣음
여기서
security:http auto-config="true" 를 쓰면
get방식의 로그인 로그아웃을 만들어줌
이게 싫으면 auto-config를 지우고 새로 만들어주면됨
logout도 마찬가지
bean class=에 BC만 쓰고 컨트롤 스페이스 누르면 클래스 나옴
나오면 맨뒤에 클래스명 복사해서 id에 붙여넣고 앞에만 소문자로 바꿔줌
그리고 여기다 붙여놈
전체코드
<?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.8.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" />
<security:http>
<security:intercept-url pattern="/oho/all" access="permitAll" />
<security:intercept-url pattern="/oho/member" access="hasRole('ROLE_MEMBER')" />
<security:form-login login-page="/sec/mylogin" login-processing-url="/sec/Login"/>
<security:logout logout-url="/mylogout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customAccessDeniedHandler">
<security:password-encoder ref="bCryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
그럼 이제 이거 만들어줘야함
참고
database-context.xml 이거 복사해서
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="driverClassName"
value="oracle.jdbc.OracleDriver"></property>
<property name="jdbcUrl"
value="jdbc:oracle:thin:@localhost:1521:XE"></property>
<property name="username" value="java"></property>
<property name="password" value="oracle"></property>
</bean>
<bean id="datasource" class="com.zaxxer.hikari.HikariDataSource"
destroy-method="close">
<constructor-arg ref="hikariConfig"></constructor-arg>
</bean>
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="configLocation" value="classpath:config/mybatis-config.xml" />
<property name="mapperLocations" value="classpath:mapper/*-Mapper.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory" />
</bean>
<mybatis-spring:scan base-package="맵퍼있는패키지"/>
</beans>
붙여넣고
<property name="username" value="pc21"></property>
<property name="password" value="java"></property>
이거바꿔주고
밑에 밑줄이 오류나는건
Mybatis를 namespace를 안지정해 줘서 나는 오류
그래서 Namespaces로 가서
mybatis-spring 체크 해주고 돌아서 저장하면 오류 없어짐
<?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:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="driverClassName"
value="oracle.jdbc.OracleDriver"></property>
<property name="jdbcUrl"
value="jdbc:oracle:thin:@localhost:1521:XE"></property>
<property name="username" value="pc21"></property>
<property name="password" value="java"></property>
</bean>
<bean id="datasource" class="com.zaxxer.hikari.HikariDataSource"
destroy-method="close">
<constructor-arg ref="hikariConfig"></constructor-arg>
</bean>
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="configLocation" value="classpath:config/mybatis-config.xml" />
<property name="mapperLocations" value="classpath:mapper/*-Mapper.xml" />
</bean>
<mybatis-spring:scan base-package="맵퍼있는패키지"/>
</beans>
이거 지정할 패키지 만들어줌
add
얘 만들어줄거임
이렇게 나오면 잘나온거
그럼 카멜케이스 null들어오면 varchar로 표기하겠다 설정
얘가 다 읽어감
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>
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.minu.sec.vo.AuthVO;
import com.minu.sec.vo.MemberVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@ExtendWith(SpringExtension.class) //JUnit5 테스트 프레임워크 사용 의미
@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")
@Disabled
public void readUser() {
MemberVO member = memberMapper.read("jinsu1");
log.debug("check {}",member);
member.getAuthList().forEach(authVO -> log.debug("{}",authVO));
}
}
package com.minu.sec.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 com.minu.sec.mapper.MemberMapper;
import com.minu.sec.vo.MemberVO;
import lombok.extern.slf4j.Slf4j;
@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);
}
}
}
package com.minu.sec.security;
import java.util.Collection;
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 com.minu.sec.vo.MemberVO;
import lombok.Getter;
@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);
}
//시큐리티가 주는 정보가 3개밖에 안되서, 우리가 필요한 걸 더 붙임(멤버필드/속성으롱)
//필요할 댸 마다 id롱 select하는 것 보다 자주쓰는 걸 그냥 붙여놓고 씀!
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-context
<?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.8.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" />
<security:http>
<security:intercept-url pattern="/oho/all" access="permitAll" />
<security:intercept-url pattern="/oho/member" access="hasRole('ROLE_SUKIL')" />
<security:form-login login-page="/sec/slogin" login-processing-url="/sec/slogin"/>
<security:logout logout-url="/mylogout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="bCryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
폼에서 name값이 username으로 고정되어있는데 이걸 변경하고 싶으면
security-context에서 변경하면 된다
나는 기본값을 쓸거기 떄문에 지운다
<%@ 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>오늘 더 멋진 석일</title>
</head>
<body>
<h1>구두가 뽀인토</h1>
<form action="/sec/slogin" method="post">
<sec:csrfInput/>
아이딩<input tyep="text" name="username" value=""><br/>
암호<input tyep="password" name="password" value=""><br/>
<button type="submit">로그잉</button>
</form>
</body>
</html>
security-context
<?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.8.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" />
<security:http>
<security:intercept-url pattern="/oho/all" access="permitAll" />
<security:intercept-url pattern="/oho/sukil" access="hasRole('ROLE_SUKIL')" />
<security:form-login login-page="/sec/slogin" login-processing-url="/sec/slogin"/>
<security:logout logout-url="/mylogout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="bCryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
root-context
security-context
<?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.8.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="com.minu.sec.security.CustomUserDetailsService" />
<security:http>
<security:intercept-url pattern="/oho/all" access="permitAll" />
<security:intercept-url pattern="/oho/sukil" access="hasRole('ROLE_SUKIL')" />
<security:form-login login-page="/slogin" login-processing-url="/slogin"/>
<security:logout logout-url="/mylogout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="bCryptPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
서버실행해서 에러 없는거 확인
security-context
<?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.8.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="com.minu.sec.security.CustomUserDetailsService"></bean>
<security:http>
<!-- 요거이 없으면 추측해야 해서 힘듬 -->
<security:access-denied-handler/>
<security:intercept-url pattern="/oho/all" access="permitAll" />
<security:intercept-url pattern="/oho/sukil" access="hasRole('ROLE_SUKIL')" />
<security:form-login login-page="/slogin" login-processing-url="/slogin"/>
<!-- username-parameter="sukilname"을 사용하면 default값인 username을 사용하지 않고 sukilname을 사용할 수 있음 -->
<!-- login-page= => get방식으로 화면보여주기 위해 / login-processing-url= => post방식 -->
<security:logout logout-url="/mylogout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService" >
<security:password-encoder ref="bCryptPasswordEncoder" />
</security:authentication-provider>
</security:authentication-manager>
</beans>
@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());
}
}
slogin.jsp
<%@ 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>오늘 더 멋진 석일</title>
</head>
<body>
<h1>구두가 뽀인토</h1>
<form action="/sec/slogin" method="post">
아이딩<input type="text" name="username" value=""><br/>
암호<input type="password" name="password" value=""><br/>
<button type="submit">로그잉</button>
</form>
</body>
</html>
security-context
<?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.8.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="com.minu.sec.security.CustomUserDetailsService"></bean>
<bean id="customAccessDeniedHandler" class="com.minu.sec.security.CustomAccessDeniedHandler" />
<security:http>
<!-- 요거이 없으면 추측해야 해서 힘듬 -->
<security:access-denied-handler ref="customAccessDeniedHandler" />
<security:intercept-url pattern="/oho/all" access="permitAll" />
<security:intercept-url pattern="/oho/sukil" access="hasRole('ROLE_SUKIL')" />
<!-- 사용자가 입력한 URL로 그대로 가게 둘때는 꼭 필요하진 않지만
로그인 성공후에 특정 URL로 보내고 싶을 때는 success-handler가 필용!
-->
<security:form-login authentication-success-handler-ref="" login-page="/slogin" login-processing-url="/slogin"/>
<!-- username-parameter="sukilname"을 사용하면 default값인 username을 사용하지 않고 sukilname을 사용할 수 있음 -->
<!-- login-page= => get방식으로 화면보여주기 위해 / login-processing-url= => post방식 -->
<security:logout logout-url="/mylogout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService" >
<security:password-encoder ref="bCryptPasswordEncoder" />
</security:authentication-provider>
</security:authentication-manager>
</beans>
@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");
}
}
security-context
<?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.8.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="com.minu.sec.security.CustomUserDetailsService"></bean>
<bean id="customAccessDeniedHandler" class="com.minu.sec.security.CustomAccessDeniedHandler" />
<bean id="customLoginSuccessHandler" class="com.minu.sec.security.CustomLoginSuccessHandler" />
<security:http>
<!-- 요거이 없으면 추측해야 해서 힘듬 -->
<security:access-denied-handler ref="customAccessDeniedHandler" />
<security:intercept-url pattern="/oho/all" access="permitAll" />
<security:intercept-url pattern="/oho/sukil" access="hasRole('ROLE_SUKIL')" />
<!-- 사용자가 입력한 URL로 그대로 가게 둘때는 꼭 필요하진 않지만
로그인 성공후에 특정 URL로 보내고 싶을 때는 success-handler가 필용!
-->
<security:form-login authentication-success-handler-ref="customLoginSuccessHandler" login-page="/slogin" login-processing-url="/slogin"/>
<!-- username-parameter="sukilname"을 사용하면 default값인 username을 사용하지 않고 sukilname을 사용할 수 있음 -->
<!-- login-page= => get방식으로 화면보여주기 위해 / login-processing-url= => post방식 -->
<security:logout logout-url="/mylogout" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService" >
<security:password-encoder ref="bCryptPasswordEncoder" />
</security:authentication-provider>
</security:authentication-manager>
</beans>
서버 리스타트
URL을 보면 로그인 되었을때 여기서 지정한 곳으로 이동하는것을 볼 수 있다.
지금 여기까지가 기본..
요기 권한을 차분하게 잘해줘야함
'Spring > Spring 기초' 카테고리의 다른 글
filezila사용해서 file전송 서버 만들기(ftp) (0) | 2023.09.01 |
---|---|
e7e샘의 시큐리티 설정4(메뉴얼 로그인) (0) | 2023.08.31 |
e7e샘의 시큐리티 설정2(멀티) (0) | 2023.08.30 |
e7e샘의 시큐리티 설정2(AJAX토큰사용/로그인페이지 설정) (0) | 2023.08.29 |
e7e샘의 시큐리티 설정 (0) | 2023.08.29 |