스프링 시큐리티 대략적인 기능
-
사용자 권한에 따른 URI 접근 제어
-
DB와 연동하는 Local strategy 로그인
-
쿠키를 이용한 자동 로그인
-
패스워드 암호화
이외에 여러 기능들이 존재합니다.
개념
시큐리티 사용을 앞서 인증(Authentication)과 권한(Authorization)이라는 개념을 알아야 합니다.
인증은 '증명하다'라는 의미로 예를 들어, 유저 아이디와 비밀번호를 이용하여 로그인하는 과정을 말합니다.
권한은 '권한 부여'나 '허가'와 같은 의미로 사용됩니다. 즉, 어떤 대상이 특정 목적을 실현하도록 허용(Access) 하는 것을 의미합니다.
Web에서 인증은 해당 URL은 보안 절차를 거친 사용자들만 접근할 수 있다는 의미이고,
권한이란 URL에 접근한 사용자가 특정한 자격이 있다는 것을 의미합니다.
package com.newlecture.web.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private DataSource dataSource;
@Override //인증 url 설정
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN") //해당 url에 해당 역할자만 들어와야함.
.antMatchers("/teacher/**").hasRole("TEACHER")
.antMatchers("/student/**").hasRole("STUDENT")
.antMatchers("/member/home").authenticated() //인증이되면 home갈 수 있게 해줌.
// /admin/ 모든 하위 경로에 ADMIN이라는 역할을 갖고있는애한테 인증을 허가한다.
.and() //우리가 만든 로그인 페이지로 넘기기
.formLogin()
.loginPage("/member/login") //GET URL
.loginProcessingUrl("/member/login") //POST URL
.defaultSuccessUrl("/index") //로그인이 성공하면 index로 넘김
.and() //csrf무효화 시키는 방법
.csrf()
.disable();
//super.configure(http); //웹이 자동으로만든 로그인 할 수 있는 페이지로 넘김(자동으로 만들어짐)
}
@Override //사용자의 권한정보, 계정정보를 설정
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//스프링 인증 3대 요소 (사용자 계정정보를 어떤걸 쓸꺼냐)
// auth.inMemoryAuthentication(); //DB를 사용하지 않고, 메모리에 저장된 내용을 사용하는 경우
// auth.jdbcAuthentication(); //정보가 DB에 있는 경우
// auth.ldapAuthentication(); //로그인시 저장되는 정보가 컨트롤러에 저장-도메인 컨트롤에 계정을 저장(사용자 프로필 관리 시스템)
// auth //메모리로 저장된 내용 사용
// .inMemoryAuthentication()
// .withUser("newlec")
// .password("{noop}111") //{noop}은 비번이 암호화 되지 않음을 뜻함.
// .roles("ADMIM")
// .and()
// .withUser("dragon")
// .password("{noop}111")
// .roles("TEACHER")
// .and()
// .withUser("DUKI")
// .password("{noop}5959")
// .roles("ADMIN");
auth //DB에 있는 내용 사용
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select uid id, pwd password, 1 enabled from Member where uid=?")
.authoritiesByUsernameQuery("SELECT uid id, 'ROLE_ADMIN' roleId FROM Member where uid=?")
.passwordEncoder(new BCryptPasswordEncoder()); //endabled 사용자가 활성화 됬냐 (휴면계정같은 느낌)
}
}
-DataSource
커넥션 풀에는 여러 개의 Connection 객체가 생성되어 운용되는데, 이를 직접 웹 애플리케이션에서 다루기 힘들기 때문에 DataSource라는 개념을 도입하여 사용합니다.
DataSource에 대해 정의하자면 아래와 같다.
-
커넥션 풀의 Connection을 관리하기 위한 객체이다.
-
JNDI Server를 통해서 이용된다.
-
DataSource 객체를 통해서 필요한 Connection을 획득, 반납 등의 작업을 한다.
spring boot는 application.properties에 datasource에 대한 설정값을 지정한다.
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
# mysql db setting
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://
spring.datasource.username=id
spring.datasource.password=123123
BCryptPasswordEncoder 인코더를 사용해 같은 문자열을 5번 출력한 경우
jsp에서 security taglib 사용하기
의존성 추가
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
<s:authorize access="hasRole('TEACHER')">
<li>관리자 페이지</li>
</s:authorize>
<li><a href="/index">${sessionScope.uid}HOME</a></li>
<c:if test="${sessionScope.uid != null}">
<li><a href="/member/logout">로그아웃</a></li>
</c:if>
<c:if test="${sessionScope.uid == null}">
<li><a href="/member/login">로그인</a></li>
</c:if>
<li><a href="/member/agree">회원가입</a></li>
<s:authorize access="hasRole('TEACHER')"> 역할자가 TEACHER인 경우만 관리자 페이지라는 문구가 보입니다.
access에 해당되는 표현식입니다.
hasRole([role]) |
현재 로그인된 사용자가 지정된 role을 가지고 있으면 true를 반환합니다. 제공된 role이 'ROLE_'로 시작하지 않으면 기본적으로 'ROLE_'를 추가합니다. 이것은 DefaultWebSecurityExpressionHandler에서 defaultRolePrefix를 수정하여 커스터마이즈 할 수 있습니다. |
hasAnyRole([role1, role2]) |
현재 로그인된 사용자가 콤마(,)로 분리하여 주어진 role들 중 하나라도 가지고 있으면 true를 반환합니다. 제공된 role이 'ROLE_'로 시작하지 않으면 기본적으로 'ROLE_'를 추가합니다. 이것은 DefaultWebSecurityExpressionHandler에서 defaultRolePrefix를 수정하여 커스터마이즈 할 수 있습니다. |
hasAuthority([authority]) |
현재 로그인된 사용자가 지정된 권한이 있으면 true를 반환합니다. |
hasAnyAuthority([authority1, authority2]) |
현재 로그인된 사용자가 콤마(,)로 분리하여 주어진 권한들 중 하나라도 가지고 있으면 true를 반환합니다. |
principal |
현재 사용자를 나타내는 principal 객체에 직접 접근할 수 있습니다. |
authentication |
SecurityContext로부터 얻은 Authentication 객체에 직접 접근할 수 있습니다. |
permitAll |
항상 true로 평가됩니다. |
denyAll |
항상 false로 평가됩니다. |
isAnonymous() |
현재 사용자가 익명 사용자(로그인 안됨) 사용자이면 true를 반환합니다. |
isRememberMe() |
현재 로그인된 사용자가 remember-me 사용자이면 true를 반환합니다.(로그인 정보 기억 기능에 의한 사용자) |
isAuthenticated() |
현재 사용자가 로그인된 사용자라면 true를 반환합니다. |
isFullyAuthenticated() |
로그인 정보 기억(remember-me)이 아니라 아이디/비밀번호를 입력하여 로그인했다면 true를 반환합니다. |
hasPermission(Object target, Object permission) |
사용자가 주어진 권한으로 제공된 대상에 액세스 할 수 있으면 true를 반환합니다. 예, hasPermission(domainObject, 'read') |
hasPermission(Object targetId, String targetType, Object permission) |
사용자가 주어진 권한으로 제공된 대상에 액세스 할 수 있으면 true 를 반환합니다. 예, hasPermission(1, 'com.example.domain.Message', 'read') |
로그인 인증
@Override //사용자의 권한정보, 계정정보를 설정
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth //DB에 있는 내용 사용
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select uid id, pwd password, 1 enabled from Member where uid=?")
.authoritiesByUsernameQuery("SELECT uid id, 'ROLE_ADMIN' roleId FROM Member where uid=?")
.passwordEncoder(new BCryptPasswordEncoder());
}
. authoritiesByUsernameQuery.authoritiesByUsernameQuery("SELECT uid id, 'ROLE_ADMIN' roleId FROM Member where uid=?")
로그인을 위해서는 SecurityConfig 클래스에 AuthenticationManagerBuilder를 주입해서 인증에 대한 처리를 해야 합니다. AuthenticationManagerBuilder는 인증에 대한 다양한 설정을 생성할 수 있습니다.
예를 들어, 메모리상 정보를 이용하거나, JDBC, LDAP 등의 정보를 이용해서 인증 처리가 가능합니다. 다음 예제는 DB에 있는 내용을 이용하는 예제입니다.
참고로 AuthenticationManagerBuilder는 인증 매니저를 생성하는 빌더입니다.
'웹 프로그래밍 기초 > 자바기반의 웹&앱 응용SW 개발자' 카테고리의 다른 글
JQuery 시작하기 (0) | 2020.06.25 |
---|---|
자바기반의 웹&앱 응용 SW개발자 양성과정 71일차 -106 (0) | 2020.06.24 |
자바기반의 웹&앱 응용 SW개발자 양성과정 69일차 -104 (0) | 2020.06.19 |
자바기반의 웹&앱 응용 SW개발자 양성과정 68일차 -103 (0) | 2020.06.18 |
자바기반의 웹&앱 응용 SW개발자 양성과정 68일차 -102 (0) | 2020.06.18 |
댓글