Gibhub - NaverLogin

5. Advanced Project

    5. 3 Other Login 

        Spring Boot is a tool that facilitates the rapid and easy development of Java-based web applications. Built on top of the Spring Framework, Spring Boot automates many configuration tasks required for starting and configuring projects, thereby enhancing productivity. When discussing it comprehensively, it can be structured into key aspects: history and evolution, core features, internal operational mechanisms, as well as use cases and ecosystem.


        Here's a detailed list of the topics


  • 5.3.1 Basic Project:
  • 5.3.2 Spring Security Configuration:
  • 5.3.3 Spring Security & Naver Login:
  • 5.3.4 Spring Security & Kakao Login:


5.3.1 Basic Project:




application.property

spring.application.name=naverexam
server.servlet.session.timeout=2h
# Database Setting
spring.datasource.dbcp2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/naverexam
spring.datasource.username=root
spring.datasource.password=1111
# JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true
# aws
cloud.aws.s3.endpoint=https://kdh0608.s3.ap-northeast-2.amazonaws.com




5.3.2 Spring Security Configuration:


SecurityConfig


package com.example.naverexam.customer;


import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests .requestMatchers(new AntPathRequestMatcher("/**")).permitAll()) .formLogin((formLogin) -> formLogin .loginPage("/signin") .defaultSuccessUrl("/") ) .logout((logout) -> logout .logoutRequestMatcher(new AntPathRequestMatcher("/signout")) .logoutSuccessUrl("/") .invalidateHttpSession(true)) ; return http.build(); } @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } }




        Customer.java


package com.example.naverexam.customer;


import java.time.LocalDateTime;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
@Data
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer cid;
@Column(unique = true)
private String username; // for SpringSecurity Policy
private String password; // for SpringSecurity Policy
private boolean enabled; // for SpringSecurity Policy
private String role; // for SpringSecurity Policy
@Column(unique = true)
private String cemail;
private String cphone;
private String caddr;
private LocalDateTime cdate;
}




repository

package com.example.naverexam.customer;



import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CustomerRepository extends JpaRepository<Customer, Integer> {

Optional<Customer> findByusername(String username); // login check

}


Service

package com.example.naverexam.customer;


import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class CustomerService implements UserDetailsService {
@Autowired
private CustomerRepository customerRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Customer> tcustomer = customerRepository.findByusername(username);
if (tcustomer.isEmpty()) {
throw new UsernameNotFoundException("You need to Sign up first...");
}
Customer customer = tcustomer.get();
List<GrantedAuthority> authorities = new ArrayList<>();
if ("ROLE_USER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
} else if ("ROLE_MANAGER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_MANAGER"));
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
return new User(customer.getUsername(), customer.getPassword(), authorities);
}
public void create(Customer customer) {
customer.setEnabled(true);
customer.setRole("ROLE_USER"); // ROLE_ADMIN, ROLE_MANAGER, ROLE_PAID...
customer.setCdate(LocalDateTime.now());
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
customer.setPassword(passwordEncoder.encode(customer.getPassword()));
customerRepository.save(customer);
}
public List<Customer> readlist() {
return customerRepository.findAll();
}
public Customer authen() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String username = userDetails.getUsername();
Optional<Customer> oc = customerRepository.findByusername(username);
return oc.get();
}

}


Controller

package com.example.naverexam.customer;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class CustomerController {

@Autowired
private CustomerService customerService;



@GetMapping("/")
public String signup() {
return "signup";
}

@PostMapping("/signup")
public String signup(Customer customer) {

customerService.create(customer);

return "signup";
}

@GetMapping("/signin")
public String signin() {
return "signin";
}

}


View



signup.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<span sec:authorize="isAnonymous()">Signin First...<a href="/signin">Sign in</a></span>
<span sec:authorize="isAuthenticated()">Welcome...<span th:text="${#authentication.name}"></span>
<span th:text="${#authentication.authorities}"></span>
<a href="/signout">Sign out</a>
</span>

<form action="/signup" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<p>ID : <input type="text" name="username">
<p>PW : <input type="password" name="password">
<p>Mail : <input type="text" name="cemail">
<p><input type="submit" value="Sign up">
</form>
</body>
</html>




signin.html

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="/signin" method="post">
<div th:if="${param.error}">
<div class="alert alert-danger">
Please, Check your ID or Password...
</div>
</div>
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<p>ID : <input type="text" name="username">
<p>PW : <input type="password" name="password">
<p><input type="submit" value="Sign in">
</form>
</body>
</html>



 




5.3.3 Naver Login:




NaverController.java


package com.example.naverexam.customer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class NaverController { @GetMapping("/naver") public String naver() { return "NaverLogin"; } @GetMapping("/naverlogin") public String naverlogin() { return "callback"; } @Autowired CustomerService customerService; @GetMapping("/logincheck") public String logincheck(@RequestParam("email") String email) { if (1 == customerService.logincheck(email)) { return "redirect:/"; // 로그인 실패 처리 , 추후 변경 }else { return "redirect:/"; // 로그인 성공 처리 , 추후 변경 } } }


NaverLogin.html

<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>네이버 로그인</title>
<script type="text/javascript" src="https://static.nid.naver.com/js/naverLogin_implicit-1.0.3.js" charset="utf-8"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
</head>
<body>
<!-- 네이버 로그인 버튼 노출 영역 -->
<div id="naver_id_login"></div>
<!-- //네이버 로그인 버튼 노출 영역 -->
<script type="text/javascript">
var naver_id_login = new naver_id_login("YOURS.............", "http://localhost:8080/naverlogin");
var state = naver_id_login.getUniqState();
naver_id_login.setButton("white", 2,40);
naver_id_login.setDomain("http://localhost:8080/");
naver_id_login.setState(state);
//naver_id_login.setPopup();
naver_id_login.init_naver_id_login();
</script>
</html>



callback.html

<!doctype html>
<html lang="ko">
<head>
<script type="text/javascript" src="https://static.nid.naver.com/js/naverLogin_implicit-1.0.3.js" charset="utf-8"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
</head>
<body>
<script type="text/javascript">
var naver_id_login = new naver_id_login("YOURS.............", "http://localhost:8080/naverlogin");
// 접근 토큰 값 출력
//alert(naver_id_login.oauthParams.access_token);
// 네이버 사용자 프로필 조회
naver_id_login.get_naver_userprofile("naverSignInCallback()");
// 네이버 사용자 프로필 조회 이후 프로필 정보를 처리할 callback function
function naverSignInCallback() {
//alert(naver_id_login.getProfileData('email'));
location.href="/logincheck?email=" + naver_id_login.getProfileData('email');
}
</script>
</body>
</html>


customerService.java

package com.example.naverexam.customer;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.stereotype.Service;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
@Service
public class CustomerService implements UserDetailsService {
@Autowired
private CustomerRepository customerRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Customer> tcustomer = customerRepository.findByusername(username);
if (tcustomer.isEmpty()) {
throw new UsernameNotFoundException("You need to Sign up first...");
}
Customer customer = tcustomer.get();
List<GrantedAuthority> authorities = new ArrayList<>();
if ("ROLE_USER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
} else if ("ROLE_MANAGER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_MANAGER"));
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
return new User(customer.getUsername(), customer.getPassword(), authorities);
}
public void create(Customer customer) {
customer.setEnabled(true);
customer.setRole("ROLE_USER"); // ROLE_ADMIN, ROLE_MANAGER, ROLE_PAID...
customer.setCdate(LocalDateTime.now());
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
customer.setPassword(passwordEncoder.encode(customer.getPassword()));
customerRepository.save(customer);
}
public List<Customer> readlist() {
return customerRepository.findAll();
}
public Customer authen() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String username = userDetails.getUsername();
Optional<Customer> oc = customerRepository.findByusername(username);
return oc.get();
}
//naver logincheck
@Autowired
private HttpServletRequest req;
public int logincheck(String username) throws UsernameNotFoundException {
Optional<Customer> tcustomer = customerRepository.findByusername(username);

if (tcustomer.isEmpty()) {
return 1;//db에 없음, 회원 가입으로
}

Customer customer = tcustomer.get();
List<GrantedAuthority> authorities = new ArrayList<>();
if ("ROLE_USER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
} else if ("ROLE_MANAGER".equals(customer.getRole())) {
authorities.add(new SimpleGrantedAuthority("ROLE_MANAGER"));
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
//스프링 시큐리티 규격에 맞게 로그인 처리
SecurityContext sc = SecurityContextHolder.getContext();
sc.setAuthentication(new UsernamePasswordAuthenticationToken(customer.getUsername(), customer.getPassword(), authorities));
HttpSession session = req.getSession(true);
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,sc);

return 0; //db에 있음, 세션 처리까지
}


}



 









1.2.4 Use Cases and Ecosystem:

   - Spring Boot is suitable for various use cases including web applications, microservices, and RESTful APIs. It is widely adopted by enterprises of all sizes, from large corporations to startups, for rapid and efficient application development and deployment.

   - With a vast ecosystem, Spring Boot provides diverse extension libraries, plugins, and tools to help developers build applications more effectively. The Spring Boot community offers continuous updates and support, enabling developers to apply the latest technologies and best practices.

한국정보시스템개발원 |
Hankook Information System Institute

austiny@snu.ac.kr / austiny@gatech.edu