Spring

Spring 일지 #18 (20210914) 화면 구현(member 로그인, security)

uni5948 2021. 9. 23. 12:29

18. member 로그인, security

-환경 설정

 *timeleaf 설치(pom.xml)

... ...

        <!-- security -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-security</artifactId>

        </dependency>

 

        <!--jstl-->

        <dependency>

            <groupId>org.springframework.security</groupId>

            <artifactId>spring-security-taglibs</artifactId>

        </dependency>

 

        <!--timeleeaf-->

        <dependency>

            <groupId>org.thymeleaf.extras</groupId>

            <artifactId>thymeleaf-extras-springsecurity5</artifactId>

        </dependency>

... ...

 

-로그인

 *login GET 생성(MemberController.java)

... ...

// 127.0.0.1:8080/ROOT/member/login

    @RequestMapping(value = { "/login" }, method = RequestMethod.GET)

    public String loginGET() {

        return "member_login";

    }

... ...

 

 *로그인 페이지 생성(member_login.jsp)

 **SecurityConfig.java에 설정한 name과 똑같이 맞춰줘야한다.(action, name)

<!DOCTYPE html>

<html lang="ko" xmlns:th="http://www.thymeleaf.org">

<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>member_login_jsp</title>

</head>

<body>

    <div style="padding: 10px;">

        <form th:action="@{/member/login}" method="post" >

            아이디 <input type="text" name="userid" placeholder="아이디 입력"/><br />

            암호 <input type="password" name="userpw" placeholder="암호 입력"/><br />

            <input type="submit" value="로그인" />

        </form>

    </div>

</body>

</html>

 

 *로그인 페이지 확인

로그인 페이지

 

-보안 설정

 *MemberDetailsService.java 생성

 **security 폴더 생성 후 MemberDetailsService.java 생성

package com.example.security;

 

import java.util.Collection;

import java.util.Optional;

 

import com.example.entity.Member;

import com.example.repository.MemberRepository;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.authority.AuthorityUtils;

import org.springframework.security.core.userdetails.User;

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

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.core.userdetails.UsernameNotFoundException;

import org.springframework.stereotype.Service;

 

//security를 제공해주는

//UserDetailsService 인터페이스를 통해 구현되는 메소드

@Service

public class MemberDetailsService implements UserDetailsService {

    @Autowired

    private MemberRepository mRepository;

 

    @Override

    public UserDetails loadUserByUsername(String usernamethrows UsernameNotFoundException {

        System.out.println(username);

 

        // 이쪽으로 아이디가 넘어오니

        // 아이디를 이용해서 정보를 가져와 User객체 타입으로 리턴해서 로그인 성공 실패 알림

        Optional<Memberobj = mRepository.findById(username); // 저장소에 String 인지 Long 인지 확인

        Member member = obj.get();

 

        // String의 권한을 Collection<GrantedAuthority>로 변환

        String[] userRoles = { member.getUserrole() };

        Collection<GrantedAuthorityroles = AuthorityUtils.createAuthorityList(userRoles);

 

        // 아이디, 암호, 권한

        User user = new User(member.getUserid(), member.getUserpw(), roles);

        return user;

    }

}

 *SecurityConfig.java 생성(SecurityConfig.java )

 **security 폴더 생성 후 SecurityConfig.java 생성

package com.example.security;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

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 // security를 적용

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // db 연동을 위해 만든 service

    @Autowired

    private MemberDetailsService mService;

 

    // 환경설정 파일에서 객체 만들기(회원가입시 암호화 방법)

    @Bean

    public BCryptPasswordEncoder bCryptPasswordEncoder() {

        return new BCryptPasswordEncoder();

    }

 

    // 기존에 정의되어 있던 메소드(supper)를 지우고 새로 작성

    @Override

    @Autowired

    protected void configure(AuthenticationManagerBuilder auththrows Exception {

        auth.userDetailsService(mService).passwordEncoder(bCryptPasswordEncoder());

    }

 

    @Override

    protected void configure(HttpSecurity httpthrows Exception {

        // 등급

        http.authorizeRequests()

                // 127.0.0.1:8080/ROOT/admin/login

                .antMatchers("/admin""/admin/*").hasAuthority("ADMIN")

                // 127.0.0.1:8080/ROOT/seller/login <= ADMIN, SELLER

                .antMatchers("/seller""/seller/*").hasAnyAuthority("ADMIN""SELLER").anyRequest().permitAll().and()

 

                // 로그인 페이지

                // 127.0.0.1:8080/ROOT/member/login

                .formLogin()

                // <form action="/member/login">

                .loginPage("/member/login").loginProcessingUrl("/member/login")

                // <input type="text" name="userid">

                .usernameParameter("userid")

                // <input type="text" name="userid">

                .passwordParameter("userpw").permitAll().defaultSuccessUrl("/").and();

                ㄴ 로그인 성공 시 home 으로 이동한다.

    }

}

 

 *home.jsp 수정

 **로그인이 되었는지 확인 및 어떤 등급으로 로그인 되었는지 확인

<!DOCTYPE html>

<html lang="ko" xmlns:th="http://www.thymeleaf.org"

    xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>home.jsp</title>

    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.min.css}"/>

    <script th:src="@{/js/bootstrap.min.js}"></script>

</head>

<body>

    <div class="container">

        <div sec:authorize="isAuthenticated()"> <!--로그인 이후-->

 

            <h3 sec:authorize="hasAuthority('ADMIN')">권한 ADMIN</h3>

            <h3 sec:authorize="hasAuthority('SELLER')">권한 SELLER</h3>

            <h3 sec:authorize="hasAuthority('CUSTOMER')">권한 CUSTOMER</h3> 

            

            인증정보 : <div sec:authentication="principal"></div>

            사용자 ID : <div sec:authentication="name"></div>

        

            <!--반드시 form 태그로 로그아웃 해야함 get은 동작안됨-->

            <form th:action="@{/member/logout}" method="post">

                <input type="submit" value="로그아웃" />

            </form>

        </div>

 

        <div sec:authorize="!isAuthenticated()"> <!--로그인 이전-->

            <a th:href="@{/member/login}">로그인</a>

            <a th:href="@{/member/join}">회원가입</a>

        </div>

    </div>

</body>

</html>

 

 *로그인 실행

customer 로그인
seller 로그인
admin 로그인
로그인 안되었을 때