Full Stack Web Developer.
Syaku (샤쿠)

Java, JS (ES6+), Spring, Spring security, jQuery, Reactjs, Bootstrap.

        

08-04 05:26


Spring Boot 2 보기 Front-end 보기 DevOps 보기 Spring 3 보기 Spring Security 3 보기

스프링 시큐리티 커스텀 로그인 : Spring Security Custom Login UserDetailsService AuthenticationProvider #4 스프링프레임워크/Spring Framework

written by Seok Kyun. Choi. 최석균


스프링 시큐리티 연재 포스팅
2014/08/29 - [개발노트/Spring] - 스프링 시큐리티 로그인 #1 : Spring Framework Security Login 스프링프레임워크 #1
2014/09/04 - [개발노트/Spring] - 스프링 시큐리티 로그인 커스텀 #2 : Spring Framework Security Login Custom 스프링프레임워크 #2
2014/09/04 - [개발노트/Spring] - 스프링 시큐리티 로그인 Handler Ajax #3 : Spring Framework Security Login Ajax 스프링프레임워크 #3
2014/10/25 - [개발노트/Spring] - 스프링 시큐리티 커스텀 로그인 : Spring Security Custom Login UserDetailsService AuthenticationProvider #4 스프링프레임워크/Spring Framework

스프링 시큐리티 커스텀 로그인 : Spring Security Custom Login UserDetailsService AuthenticationProvider #4 스프링프레임워크/Spring Framework


개발환경

Mac OS X 10.9.4
JAVA 1.6
Apache Tomcat 7.x
Spring 3.1.1
Spring security 3.1.1
Spring Tool Suite 3.5.1
Maven 2.5.1

이번에는 로그인 처리를 스프링 자체에서 처리하지 않고 직접 비지니스로직을 구현해보도록 한다.

로그인 처리를 직접 구현하는 데 사용하는 인터페이스는 UserDetailsService 와 AuthenticationProvider 가 있다.

인증처리 과정
1) 접속자가 계정과 암호를 입력한다.
2) 접속자가 입력한 계정을 이용하여 데이터베이서에서 사용자 정보를 조회한 결과를 UserDetailsService 담는 다.

정확하게 말해 UserDetailsService 에 담는 것이 아니라 비지니스 로직을 처리하는 일을 하고 UserDetails 라는 곳에 담긴다.
기본적으로 계정 암호 권한룰 그외 몇가지만 설정되어 있어 필요에 따라 항목을 추가하면 된다.

3) 접속자가 입력한 계정과 암호를 사용자 정보의 계정과 암호를 비교하여 일치 한다면 사용자 정보를 사용할 수 있게 허가 한다. 이 일을 담당하는 것이 AuthenticationProvider 가 하는 역활이다.

그래서 나는 UserDetailsService 와 UserDetails 만 직접 개발하고 AuthenticationProvider 는 스프에서 처리하게 구현하였다.

이제 실제 소스를 참고하면 이해가 쉬울 것 이다. (이전 포스팅 소스를 사용하여 연결되는 소스이니 참고한다.)

@소스 servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd
    ">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled" />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="com.syaku.security" use-default-filters="false">
    <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation" />
    </context:component-scan>

</beans:beans>

@소스 security-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans 
    xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd
    ">

    <context:component-scan base-package="com.syaku.security.." use-default-filters="false">
    <context:include-filter expression="org.springframework.stereotype.Service" type="annotation" />
    <context:include-filter expression="org.springframework.stereotype.Repository" type="annotation" />
    </context:component-scan>

    <http auto-config="true" use-expressions="true" access-denied-page="/denied">

    <form-login
    login-page="/signin"
    username-parameter="user_id" 
    password-parameter="password"
    login-processing-url="/signin_ok"
    authentication-success-handler-ref="signinSuccessHandler"
    authentication-failure-handler-ref="signinFailureHandler"
    default-target-url="/mypage"
    always-use-default-target="false"
    />

    <logout
    invalidate-session="true"
    logout-success-url="/signin"
    logout-url="/signout" />

    </http>

    <beans:bean id="signinSuccessHandler" class="com.syaku.security.SigninSuccessHandler" />
    <beans:bean id="signinFailureHandler" class="com.syaku.security.SigninFailureHandler">
        <beans:property name="defaultFailureUrl" value="/signin?error=true" />
    </beans:bean>

    <!--
    <authentication-manager>
        <authentication-provider>
            <password-encoder ref="passwordEncoder"/>
            <user-service>
                <user name="guest" password="35675e68f4b5af7b995d9205ad0fc43842f16450" authorities="ROLE_USER"/>
                <user name="admin" password="d033e22ae348aeb5660fc2140aec35850c4da997" authorities="ROLE_ADMIN"/>
            </user-service>
        </authentication-provider>
    </authentication-manager>
    -->

    <beans:bean id="userService" class="com.syaku.security.model.UserService" />

    <beans:bean id="encoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" />
    <beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
        <beans:property name="userPropertyToUse" value="username" />
    </beans:bean>

    <authentication-manager>
        <authentication-provider user-service-ref="userService">
            <password-encoder ref="encoder">
                <salt-source ref="saltSource" />
            </password-encoder>
        </authentication-provider>
    </authentication-manager>

</beans:beans>

userDetailsService 빈이 추가되었다. 그리고 암호가 변동되지 않게 salt-source 를 설정하였다.

[2014.11.05] 내용 수정
salt-source 를 설정하지 않으면 입력한 비밀번호 암호된 값이 매번 바뀌게 된다. 변경되지 않아야 암호화된 값을 비교할 수 있어 수정하였다.

@소스 Privilege.java

package com.syaku.security.model.domain;

public class Privilege {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

@소스 Role.java

package com.syaku.security.model.domain;

import java.util.List;
import org.springframework.security.core.GrantedAuthority;


public class Role implements GrantedAuthority {
    private static final long serialVersionUID = 1L;

    private String name;
    private List<Privilege> privileges;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getAuthority() {
        return this.name;
    }

    public List<Privilege> getPrivileges() {
        return privileges;
    }
    public void setPrivileges(List<Privilege> privileges) {
        this.privileges = privileges;
    }
}

@소스 User.java

package com.syaku.security.model.domain;

import java.util.Collection;
import java.util.List;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;


public class User implements UserDetails {
    private static final long serialVersionUID = 1L;

    private String username;
    private String password;

    // 추가적인 회원정보 항목을 추가한다. email 이나 연락처 등등...

    private List<Role> authorities;
    private boolean accountNonExpired = true;
    private boolean accountNonLocked = true;
    private boolean credentialsNonExpired = true;
    private boolean enabled = true;

    @Override
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    public void setAuthorities(List<Role> authorities) {
        this.authorities = authorities;
    }

    @Override
    public boolean isAccountNonExpired() {
        return this.accountNonExpired;
    }

    public void setAccountNonExpired(boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }

    @Override
    public boolean isAccountNonLocked() {
        return this.accountNonLocked;
    }

    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return this.credentialsNonExpired;
    }

    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }

    @Override
    public boolean isEnabled() {
        return this.enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}

@소스 UserService.java

package com.syaku.security.model;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.syaku.security.model.domain.Role;
import com.syaku.security.model.domain.User;

@Service
public class UserService implements UserDetailsService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);

    @Override
    public User loadUserByUsername(final String username) throws UsernameNotFoundException {

        logger.info("username : " + username);

        // 회원 정보 dao 에서 데이터를 읽어 옴.

        // test 값을 암호화함.
        String password = "aabcb987e4b425751e210413562e78f776de6285";

        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        Role role = new Role();
        role.setName("ROLE_USER");

        List<Role> roles = new ArrayList<Role>();
        roles.add(role);
        user.setAuthorities(roles);

        // 만약 데이터가 없을 경우 익셉션
        //if (user == null) throw new UsernameNotFoundException("접속자 정보를 찾을 수 없습니다.");

        return user;
    }
}

UserService 에서는 사용자 정보를 가져오는 DAO 를 통해 정보를 담는 역활을 한다. 암호는 임의적으로 암호화된 코드를 이용하여 생성하였다.
이제 로그인 테스트를 해보면 정상적인 처리가 이루어 질 것이다. 계정은 test 암호 test 로 접속하여 테스트 한다.

만약 로그인 처리까지 직접 비지니스 로직을 구현하고 싶다면 AuthenticationProvider 이용해서 구현하면 된다.

우선 security-context.xml 에서 authentication-manager 를 아래와 같이 수정한다.

<beans:bean id="encoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder" />

<beans:bean id="userService" class="com.syaku.security.model.UserService" />
<beans:bean id="customAuthenticationProvider" class="com.syaku.security.CustomAuthenticationProvider" />

<!-- 
<authentication-manager>
    <authentication-provider user-service-ref="userService">
        <password-encoder ref="encoder">
            <salt-source ref="saltSource" />
        </password-encoder>
    </authentication-provider>
</authentication-manager>
-->

<authentication-manager alias="authenticationManager">
    <authentication-provider ref="customAuthenticationProvider" />
    <authentication-provider user-service-ref="userService">
        <password-encoder ref="encoder">
            <salt-source ref="saltSource" />
        </password-encoder>
    </authentication-provider>
</authentication-manager>

authenticationManager 에 customAuthenticationProvider 가 추가되었고 빈도 추가되었다.

[2015.03.03] 계정이 없다는 UsernameNotFoundException 아무리 호출해도... onAuthenticationFailure 에서는 BadCredentialsException 자꾸 찾길래... 원인은 customAuthenticationProvider 밑에 있는 userService 였다!! 그래서 그부분을 주석 처리한다!!!

<authentication-manager alias="authenticationManager">

    <authentication-provider ref="customAuthenticationProvider" />

    <!--

    <authentication-provider user-service-ref="userService">

        <password-encoder ref="encoder">

            <salt-source ref="saltSource" />

        </password-encoder>

    </authentication-provider>

    -->

</authentication-manager>




@소스 CustomAuthenticationProvider.java

package com.syaku.security;

import java.util.Collection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import com.syaku.security.model.UserService;
import com.syaku.security.model.domain.User;

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
    private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);

    @Autowired
    UserService userService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private SaltSource saltSource;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = (String) authentication.getCredentials();

        User user;
        Collection<? extends GrantedAuthority> authorities;

        try {

            user = userService.loadUserByUsername(username);

            String hashedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user));

            logger.info("username : " + username + " / password : " + password + " / hash password : " + hashedPassword);
            logger.info("username : " + user.getUsername() + " / password : " + user.getPassword());

            if (!hashedPassword.equals(user.getPassword())) throw new BadCredentialsException("비밀번호가 일치하지 않습니다.");

            authorities = user.getAuthorities();
        } catch(UsernameNotFoundException e) {
            logger.info(e.toString());
            throw new UsernameNotFoundException(e.getMessage());
        } catch(BadCredentialsException e) {
            logger.info(e.toString());
            throw new BadCredentialsException(e.getMessage());
        } catch(Exception e) {
            logger.info(e.toString());
            throw new RuntimeException(e.getMessage());
        }

        return new UsernamePasswordAuthenticationToken(user, password, authorities);
    }

    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }
}

모든 작업이 완료되었다. 다음에는 서비스에 대한 권한을 커스텀하게 설정할 수 있는 방법을 구현해보도록 하겠다.

[추가] access-denied-page 대신 access-denied-handler 사용하기

access-denied-handler 는 알겠지만 권한이 없는 페이지에 접속했을 때 호출되는 기능이다. page 와 다르게 백그라운드에서 구동되는 핸들러이다. 그래서 ajax 구현할때 유용하게 사용할 수 있다.

// access-denied-page 속성을 지운다.
<http auto-config="true" use-expressions="true" access-denied-page="/denied">

... 내용 생략 ...

// http 사이에 access-denied-handler 추가한다.
<access-denied-handler ref="accessFailureHandler" />
</http>

<beans:bean id="accessFailureHandler" class="com.syaku.tag.user.AccessFailureHandler">
// access-denied-page 페이지도 적용하고 싶다면 아래와 같이 추가하면 된다.
<beans:property name="errorPage" value="/403" />
</beans:bean>

이전에 만들었던 SigninFailureHandler,SigninSuccessHandler 와 크게 다르지 않다. 참고해서 개발하면 된다.

@소스 AccessFailureHandler.java

package com.syaku.tag.user;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;

public class AccessFailureHandler implements AccessDeniedHandler {
    private static final Logger logger = LoggerFactory.getLogger(AccessFailureHandler.class);

    private String errorPage;

    public AccessFailureHandler() {
    }

    public AccessFailureHandler(String errorPage) {
        this.errorPage = errorPage;
    }

    public String getErrorPage() {
        return errorPage;
    }

    public void setErrorPage(String errorPage) {
        this.errorPage = errorPage;
    }

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exception) throws IOException, ServletException {

        String accept = request.getHeader("accept");

        String error = "true";
        String message = exception.getMessage();

        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setCharacterEncoding("UTF-8");

            String data = StringUtils.join(new String[] {
                " { \"response\" : {",
                " \"error\" : " , error , ", ",
                " \"message\" : \"", message , "\" ",
                "} } "
            });

            PrintWriter out = response.getWriter();
            out.print(data);
            out.flush();
            out.close();

    }
}
스프링 시큐리티 새로운 암호화 체계

설정

<beans:bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
@Autowired private PasswordEncoder passwordEncoder;

// 입력한 암호를 암호화 한다.
String bcryptPassword = passwordEncoder.encode(password);

// matches 를 이용하여 암호를 비교한다.
if ( !passwordEncoder.matches(password, consumer.getPassword()) ) {
    throw new BadCredentialsException( "암호가 일치하지 않습니다." );
}

스프링 시큐리티의 새로운 암호화 방식은 암호화를 할때마다 새로운 암호화된 코드가 생성된다.
그래서 saltSource 를 사용하지 않아도 되며 비교할때는 꼭 matches 메서드를 이용해야 한다.

[참고] 최초로 암호화된 정보를 디비에 저장하고 그 후에는 저장하지 않고 비교만 하면된다.

PS. ㅡㅡ 참 좋은 하루패드가 점점 이상해지네요;; 설정이 초기화될때도 많고... 코드하이라이트가 저렇게 두줄이나오고 좋았는데... 이제 뭘로 해야하나;;;

posted syaku blog

Syaku Blog by Seok Kyun. Choi. 최석균.

http://syaku.tistory.com

  • 자바무능자 at 2015.07.30 20:20

    샤쿠님 강좌보면서 제가 연습하던 Spring mvc모델에 시큐티리 적용하려고 하는데
    자꾸 이곳저곳에서 에러가 발생하네요 ㅠㅠ;
    혹시 지금 현재 시큐리티 강좌코드좀 올려주실수 없으신가요...ㅠ;

    • 샤쿠 syaku at 2015.07.31 09:41 신고

      정리되어 있는 소스가 당장은 없는 지라;;; 그리구 강좌는 아니구요 제가 공부하면 정리한 것들입당~ 오류 내용을 올려주시면 답변해드릴게요~

  • 개발자 at 2015.12.22 20:28

    LoginService 에서 다른 서비스를 호출하는 방법은 없나요?

    다른 서비스에 있는 쿼리를 읽어오고 싶은데 계속 에러가 나네요 ㅠㅠ

    어떻게 해야 하는지 궁금하군요

  • 초보자 at 2016.02.04 10:20

    아.. 제가 어제 켜놓은 상태에서 글을 수정해서 문의글을 바꿧는데
    답글을 이제서야 봤네요 ㅎㅎ.. 보니까 WEB.XML의 문제였습니다.
    수정했습니다.
    답변 감사합니다.

    • 샤쿠 syaku at 2016.02.04 09:54 신고

      SqlSession 없거나 찾을 수 없는 것 같네요~
      sqlSession 직접 di 하셨으면 애플리케이션 컨텍스트(*-context.xml) 설정에서 id 값을 확인하고 그 값을 그대로 Qulifier 에 넣어주세요

      일반적으로 Mybatis 설정은 따로 sqlsession 호출해서 사용하지 않습니다.

      mapper.xml -> mapperInterface.java -> mapperDao.java

      순으로 연결하고 최종 mapperDao 를 서비스에서 사용합니다.

      spring 이 자동으로 맵퍼를 로드하여 mapperInterface 와 연결시켜줍니다.
      확장성을 고려하여 mapperDao(interface)를 추가한것입니다.

  • 초보자 at 2016.02.04 10:20

    답변 너무 감사합니다.

    1. 저는 DB에 권한 컬럼을 만들어놓고
    사용자마다 ROEL_USER인지 ROLE_ADMIN인지를 설정해놨습니다.
    이 부분을 통해서 권한을 주고 싶은데요
    권한을 설정할 수 있을까요? CustomAuthenticationProvider 부분에서?

    2. 만약에 ENCODER 가 아니라 암호화 된DB 값을 DECODER해야할 경우에는 어떻게 하는게 좋을까요?

    • 샤쿠 syaku at 2016.02.04 10:50 신고

      1. [본문참고] UserService 클래스에서 loadUserByUsername 메서드에서 그 역활을 합니다.
      디비의 권한 정보를 읽어와서
      List<Role> roles = new ArrayList<Role>(); 에 넣어주시면 됩니다.

      // 디비에서 권한 조회 후 결과를..
      roles.add(권한롤);

      // 시큐리티에 적용
      user.setAuthorities(roles);

      2. [본문참고] CustomAuthenticationProvider 클래스에서 관리합니다.
      authenticate 메서드에서 최종 사용자를 검증합니다.

      해독이가능한 암호화를 사용하시면 됩니다.
      (https://commons.apache.org/proper/commons-codec)

      // 입력 받은 암호
      String password = (String) authentication.getCredentials();

      // 디비의 암호
      user = userService.loadUserByUsername(username);
      String _password = user.getPassword();

      // 1. 입력받은 암호를 아파치 코덱으로 암호화 합니다.
      // 2. 디비의 암호도 암호화 합니다.

      // 1과 2를 비교합니다 틀릴 경우 익셉션을 발생시킵니다.
      if (!_password.equals(password())) throw new BadCredentialsException("비밀번호가 일치하지 않습니다.");

      // 같을 경우 인증을 허락합니다.

      return new UsernamePasswordAuthenticationToken(user, password, user.getAuthorities());



      [참고] 디비에 저장된 암호도 암호화하여 저장하는 것이 보안상 안전합니다.


    • 초보자 at 2016.02.04 11:19

      답변 감사합니다.
      1. 제가 server에서 권한을 줬으니 이제 뷰에서

      회원 권한이 있을 때
      sec:authorize ifAnyGranted="ROLE_USER"
      안녕하세요
      /sec:authorize


      이렇게 체크해주면 될것같네요 .. 맞나요..?

      2. 예로 a라는 user에 평가를 내리는데 평가내용이 좋지 못한경우에는 admin만 봐야하는데 나중에도 그 결과를 봐야하는데 db에 그냥 나쁜 평가를 적어두면 문제가 되지 않을가 해서 걱정했습니다.

      너무너무 답변 감사합니다.

    • 샤쿠 syaku at 2016.02.04 14:48 신고

      1. 맞습니다.

      2. 룰과 퍼미션은 약간 개념이 다릅니다.....
      롤에 ROLE_ADMIN 이라고해서 모든권한을 부여받는 그런것이아니라 단순히 의미를표시하기 위한 이름일 뿐입니다.

      security.authorize access="hasAnyRole('ROLE_USER', 'ROLE_MANAGER')
      위는 ROLE_UEER 와 ROLE_MANAGER 모두가 볼수 있지만
      만약 ROLE_USER 만 있다면 ROLE_MANAGER 볼수 없죠~

      그래서 퍼미션을 부여해서 ROLE_ADMIN 은 모든 권한을 가질수 있는 시스템을 구현해야 시큐리티의 최종 목표까지 완성되는 거라 생각합니다...

      제 블로그에는 퍼미션에 대한 부분까지 공개하지 않은 상태입니다~ 계획은 있으나 시간이 없어서...

      여튼 저도 공부하면서 정리한거라 부족한 부분이 많을 텐데 도움이 되셨다니 다행입니다.

  • 초보자 at 2016.02.25 09:25

    안녕하세요 샤쿠님 궁금한게 있어서 질문 올립니다.
    제 로컬에서는 접속이 되는데 제 pc든 다른pc에서 제 아이피를쓰고 접속하려고하면 안되는 이유가 뭔가요?
    예로 localhost:8080/chobo/login으로 접속되던것이 제 아이피가 111.11.11이면 111.11.11:8080/chobo/login 으로는 접속이 안됩니다;
    이떤 이유때문인지 알 수 있을까요?

    • 샤쿠 syaku at 2016.02.25 09:31 신고

      방화벽에 막혀있어서 그럴듯합니다.

    • 초보자 at 2016.02.25 11:45

      항상 답변 감사합니다. 더 많이 배우고 갑니다!

    • 초보자 at 2016.06.22 16:52

      샤쿠님 안녕하세요!
      자주 샤쿠님 티스토리에 접속하여 많이 배우고 갑니다!!
      커스텀설정중에 궁금한점이 있어서 여쭤보고 싶은 부분이 있어서 글 올립니다. 4개월만에

      로그인 정보가 있을경우에 /mypage 를 입력하면 mypage로 들어가고
      로그인 정보가 없을시에 /mypage 입력시에 /signin으로 돌아옵니다.
      그런데 저는 이부분이 어디서 설정되는지를 잘 모르겠습니다;

      login페이지와 mypage를 나누셧는데, 저는 index 페이지안에 div상단 -> 메뉴 하단-> login,mypage를 설정해두어서
      /mypage로 접근하면 로그인 정보가 없을시에는 / <- 여기로 바로 그냥 오고싶은데
      어디서 설정하는 부분인지 이해가 안갑니다..

    • 샤쿠 syaku at 2016.06.23 08:39 신고

      <form-login
      login-page="/signin" // 로그인 페이지 호출
      />

      기본적으로 로그인 정보가 없을 경우 login-page를 호출하게 됩니다. 그래서 해당 경로를 수정하시면 됩니다.
      그러나 로그인 페이지는 직접 url를 입력하여 접근하던가 버튼이나 링크를 만들어 클릭하여 접근할 수 있게 유도해야합니다.



      혹은 AuthenticationEntryPoint 필터를 이용하여 제어할 수 있습니다.

    • 초보자 at 2016.06.23 10:51

      샤쿠님 천재 감사합니다.

  • 김규현 at 2016.04.06 15:22

    안녕하세요 샤쿠님!
    혹시 시큐리티 커스텀 이적용된
    폴더 트리구조좀 스크린샷이나 볼수있을까요???
    어디에 만들어야하는지 생성하는지
    위에 패키지 써있는것 보아도 잘모르겠어서요 헷갈려서..

  • 1234 at 2017.03.21 10:50

    스프링 배운지가 2년됐는데.. 샤쿠님덕에 많은 도움 됐네요.. 너무너무 감사드립니다

댓글 남기기
◀ PREV 1···838485868788899091···313 NEXT ▶