본문 바로가기

카테고리 없음

수업내용_21/02/19

1. 암호화 방법

· 입력된 패스워드는 인코딩을 통해 암호화되어 DB에 저장되고, 입력된 패스워드와 일치하는지 확인하기 위해 DB에서

  조회한 패스워드는 디코딩을 거쳐 원래의 패스워드로 변경하여 확인하는 과정을 거친다.

· 회원가입 할 때, customNoOpPasswordEncoder의 모듈을 이용하여 password를 매칭시키고, bcryptPasswordEncoder

  모듈을 통해 인코딩 과정을 거쳤으므로, password-encoder ref를 bcryptPasswordEncoder를 사용해야 디코딩이 가능하다.

 

<security-db-context.xml>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    <beans:bean id="customNoOpPasswordEncoder" class="edu.bit.ex.security.CustomNoOpPasswordEncoder"/>
     <!-- 암호화 모듈 -->
     <beans:bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
   
   <!-- provider --> 
   <authentication-manager>
      <authentication-provider>
      <password-encoder ref="bcryptPasswordEncoder"/> 
         <jdbc-user-service 
               data-source-ref="dataSource"
               role-prefix=""
               users-by-username-query="select username, password, enabled from users where username = ?"
               authorities-by-username-query="select username, authority from authorities where username = ?"
           /> 
      </authentication-provider>
   </authentication-manager>
cs

 

2. 스프링 시큐리티에서 커스텀마이징 방법

· xml에서는 username, password, enabled 세 가지 정보만 가져올 수 있기 때문에 커스텀마이징을 통해 확장하여
  JSP에서 session 객체를 통해 다른 정보를 가져온다.  · 
· MemberDetailsService 객체를 생성하여 로그인 하는 경우, Service의 loadUserByUsername을 호출한다.

 

<security-custom-context.xml>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/login/loginForm" access="permitAll" />
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/admin/**" access="hasRole('ADMIN')" />
        <intercept-url pattern="/**" access="hasAnyRole('USER', 'ADMIN')" />
      
      <!--로그인 페이지 커스텀 화    -->
      <form-login login-page="/login/loginForm"
                    default-target-url="/"
                    authentication-failure-url="/login/loginForm?error"
                    username-parameter="id"
                    password-parameter="password" />
      
      <logout logout-url="/logout" logout-success-url="/" /> 
                
      <!-- 403 에러 처리 -->
      <access-denied-handler error-page="/login/accessDenied"/>      
   </http> 
      
    <beans:bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />       
 
    <beans:bean id="customNoOpPasswordEncoder" class="edu.bit.ex.security.CustomNoOpPasswordEncoder"/>
    <beans:bean id="memberDetailsService"   class="edu.bit.ex.security.MemberDetailsService" />
 
   <authentication-manager>
      <authentication-provider user-service-ref="memberDetailsService">
         <password-encoder ref="customNoOpPasswordEncoder"/>      
      </authentication-provider>
   </authentication-manager>    
</beans:beans>
cs

 

<HomeController.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Log4j
@Controller
public class HomeController {
 
   @RequestMapping(value = "/", method = RequestMethod.GET)
   public String home(Locale locale, Model model) {
      log.info("Welcome home! The client locale is {}.");
      return "home";
   }
 
   @GetMapping("/user/userHome")
   public void userHome() {
      log.info("userHome ...");      
   }
 
   @GetMapping("/admin/adminHome")
   public void adminHome() {
      log.info("adminHome ...");
   }
   
   @GetMapping("/login/accessDenied")
   public void accessDenied(Model model) {
      log.info("Welcome Access Denied!");
   }
   
   @GetMapping("/login/loginForm")
   public String loginForm() {
      log.info("Welcome Login Form!");
      return "login/loginForm2";
   }
}
cs

 

<home.jsp>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 <body>
    <h1>메인페이지</h1>
 
    <sec:authorize access="isAnonymous()">
       <p><a href="<c:url value="/login/loginForm" />">로그인</a></p>
    </sec:authorize>
 
    <sec:authorize access="isAuthenticated()">
        <form:form action="${pageContext.request.contextPath}/logout" method="POST">
       <input type="submit" value="로그아웃" />
        </form:form>
           <p><a href="<c:url value="/loginInfo" />">로그인 정보 확인 방법3 가지</a></p>
    </sec:authorize>
 
    <h3>
        [<a href="<c:url value="/user/userForm" />">회원가입</a>]
        [<a href="<c:url value="/user/userHome" />">유저 홈</a>]
        [<a href="<c:url value="/admin/adminHome" />">관리자 홈</a>]
    </h3>
 </body>
cs

 

<AuthVO.java>

1
2
3
4
5
6
7
8
9
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@ToString
public class AuthVO {
   private String username;
   private String authority;
}
cs

 

<MemberVO.java>

1
2
3
4
5
6
7
8
9
10
11
12
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@ToString
public class MemberVO {
   private String username;
   private String password;
   private String enabled;
   
   private List<AuthVO> authList;
}
cs

 

<MemberMapper.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 <mapper namespace="edu.bit.ex.mapper.MemberMapper">
    <resultMap type="edu.bit.ex.vo.MemberVO" id="memberMap">
        <result column="username" property="username" />
        <result column="password" property="password" />
        <result column="enabled" property="enabled" />
        <collection property="authList" resultMap="authMap" />
    </resultMap>
 
    <resultMap type="edu.bit.ex.vo.AuthVO" id="authMap">
        <result column="username" property="username" />
        <result column="authority" property="authority" />
    </resultMap>
 
    <select id="getMember" resultMap="memberMap">
        <![CDATA[
            select * from users, authorities where users.username=authorities.username and users.username = #{username} 
        ]]>
    </select>
 </mapper>
cs

 

<MemberDetailsService.java> UserDetails 타입으로 리턴 하기 위해 그에 맞는 타입으로 변환!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Log4j
@Service
public class MemberDetailsService implements UserDetailsService  {
   
   @Setter(onMethod_ = @Autowired)
   private MemberMapper memberMapper;
   
   @Override
   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      
      log.warn("Load User By MemberVO number: " + username);      
      MemberVO vo = memberMapper.getMember(username);      
      
      log.warn("queried by MemberVO mapper: " + vo);
      
      return vo == null ? null : new MemberUser(vo);
   }
}
cs

 

<MemberUser.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Setter
@Getter
@ToString
public class MemberUser extends User {
    private MemberVO member;
 
    // 기본적으로 부모의 생성자를 호출해야만 정상적으로 작동
    public MemberUser(String username, String password, Collection<extends GrantedAuthority> authorities) {
        super(username, password, authorities);
    }
 
    public MemberUser(MemberVO memberVO) {
        super(memberVO.getUsername(), memberVO.getPassword(), getAuth(memberVO));
 
        this.member = memberVO;
    }
 
    // 유저가 갖고 있는 권한 목록
    public static Collection<extends GrantedAuthority> getAuth(MemberVO memberVO) {
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        for (AuthVO auth : memberVO.getAuthList()) {
            authorities.add(new SimpleGrantedAuthority(auth.getAuthority()));
        }
 
        return authorities;
    }
}
cs

 

<userHome.jsp>

1
2
3
4
5
6
7
8
9
10
11
12
 <html lang="ko">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <title>유저 페이지</title>
 </head>
 <body>
    <h1>유저 페이지 입니다.</h1>
    <p>principal: <sec:authentication property="principal"/></p>
    <p>사용자이름: <sec:authentication property="principal.member.username"/></p>
    <p><a href="<c:url value="/" />"></a></p>
 </body>
 </html>
cs

 

<로그인 전/후>

 

<유저 홈, member 정보 출력 화면>