개인 자료 정리 홈페이지 입니다.

Note > 스프링시큐리티 jwt 적용하기로그인 페이지 설정과 로그인 처리부분

By a3040, Published on Invalid Date


  1. 로그인 페이지 설정
  2. 로그인 처리후 토큰 발급 : 간단히 정의한 provider[ db에서 id를 기준으로 찾아온] id, pwd와 로그인 폼에서 받은 id, pwd를 비교합니다.


로그인 페이지 설정

@Configuration
public class SecurityConfig {
...

    @Bean
    public SecurityFilterChain jwtSecurityFilterChain(HttpSecurity http) throws Exception {
...

        http.authorizeHttpRequests((requests) -> requests
...
                .requestMatchers("/css/**", "/js/**", "/error").permitAll() // 정적자원 허용
                .requestMatchers("/member/loginProc").permitAll() // html막테스트
                .formLogin((form) -> form
                        .loginPage("/member/login").permitAll()
...
                )
                .logout((logout) -> logout.permitAll()
                        .deleteCookies("jwt")
                        .invalidateHttpSession(false)
                        .logoutSuccessUrl("/member/login"));


        return http.build();
    }


로그인 처리 및 토큰 발급


@RestController
public class AuthenticationController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;

    @Autowired
    private UserRepository userRepository;

    @PostMapping("/member/loginProc")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) throws Exception {
        try {
            authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
        } catch (BadCredentialsException e) {
            throw new Exception("Incorrect username or password", e);
        }
        final User user = userRepository.findByUsername(loginRequest.getUsername());
        final UserDetails userDetails = jwtUserDetailsService.loadUserByUsername(user.getUsername());
        final String token = jwtTokenUtil.generateToken(userDetails);
        return ResponseEntity.ok(new LoginResponse(token));
    }

    // ...
}




            authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));


이 과정에서 일어나는 일


  1. UsernamePasswordAuthenticationToken 객체를 생성합니다. 이 객체에는 사용자가 입력한 로그인 폼 정보가 포함됩니다.
  2. AuthenticationManager 구현체 중 하나인 ProviderManager 객체를 생성합니다. 이 객체는 여러 개의 AuthenticationProvider를 가질 수 있습니다.
  3. ProviderManagerauthenticate() 메서드를 호출합니다. 이 메서드는 등록된 AuthenticationProvider에서 인증을 처리합니다.
  4. DaoAuthenticationProvider 객체를 생성하여 ProviderManager에 추가합니다. 이 객체는 DB에서 사용자 정보를 가져와 인증을 처리합니다.
  5. DaoAuthenticationProvideradditionalAuthenticationChecks() 메서드를 호출하여 사용자 정보를 인증합니다. 이 메서드에서는 DB에서 가져온 사용자 정보와 로그인 폼 정보를 비교합니다.



Note > 스프링시큐리티 jwt 적용하기Authentication / AuthenticationManager/ DaoAuthenticationProvider

By a3040, Published on Invalid Date

AuthenticationEntryPoint 인증정보를 요청하는 응답에 사용 이후 Login 페이지등으로 이동합니다.

사용자가 보낸 인증을 위한 정보(id/pwd)가 Authentication 에 담기게 됩니다.


AuthenticationManager 가 db에있는 정보와 보내온 인증정보를 비교해서 인증여부를 판단합니다.

authenticationManager.authenticate() 메서드에서는 DaoAuthenticationProvider 객체를 사용하여 DB에서 사용자 정보를 가져와 인증을 처리하고, additionalAuthenticationChecks() 메서드에서 로그인 폼 정보와 DB 정보를 비교합니다.


@Service
public class JwtUserDetailsService implements UserDetailsService {
...
    
    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        Member member = memberRepository.findByEmail(email);
        if (member == null) {
            throw new UsernameNotFoundException("User not found with email: " + email);
        }
    return new User(member.getEmail(), member.getPassword(), Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")));
        }
    



@Configuration
public class SecurityConfig {
...
    
    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;
    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); 
        provider.setPasswordEncoder(new PlaintextPasswordEncoder());//일반 문자열비교
        // provider.setPasswordEncoder(new BCryptPasswordEncoder());
        provider.setUserDetailsService(jwtUserDetailsService);
        return provider;
    }


    @Bean
    public SecurityFilterChain jwtSecurityFilterChain(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .headers()
                .frameOptions().disable();
        http.cors()
        .configurationSource(corsConfigurationSource());
        http.authenticationProvider(daoAuthenticationProvider());
        ....
}

class PlaintextPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence rawPassword) {
        return rawPassword.toString();
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return rawPassword.toString().equals(encodedPassword);
    }
}





Note > 자바스크립트 관련화살표함수

By a3040, Published on Invalid Date

정말 이해가 힘든 부분이 많습니다.

읽는건 가능해도 이렇게는 못만들듯 합니다.


  <button className="absolute top-0 right-0 p-2" onClick={handleClick(memo.key)}>

  const handleClick = (key) => (e) => {
    console.log(key);
    console.log(e);
  };


좀 이해가 쉬운 형태는

  <button className="absolute top-0 right-0 p-2"  onClick={(e) => handleClick(memo.key, e)}>

  function handleClick(key, e) {
    console.log(key);
    console.log(e);
  }


이 형태인걸 같습니다.

Note > 우분투에서 Springboot ssl 설정하기--

By a3040, Published on Invalid Date

  1. certbot 설치하기
$ sudo apt-get update
$ sudo apt-get install certbot
  1. 인증서 발급받기
$ sudo certbot certonly --webroot -w /var/www/html -d example.com



설치 과정에서 /var/www/html 위치에 파일을 만들고 확인을 진행하는데 

이를 실패할 경우 따로 파일을 만들어 주거나 하고 다시 진행을 수행합니다.


/var/www/html/.well-known/acme-challenge/2m4aHw_W5QHOytip2DwvqnQhMSQuvZs3CCIwRIUJsPU  

이런 파일을 만들어 달라고 하거나 권한이 될경우 스스로 만듭니다.


인증서 발급에 성공하면


/etc/letsencrypt/live/도메인 위치에


lrwxrwxrwx 1 root root  38 Mar 27 15:57 cert.pem -> ../../archive/a3040.com-0001/cert1.pem

lrwxrwxrwx 1 root root  39 Mar 27 15:57 chain.pem -> ../../archive/a3040.com-0001/chain1.pem

lrwxrwxrwx 1 root root  43 Mar 27 15:57 fullchain.pem -> ../../archive/a3040.com-0001/fullchain1.pem 

lrwxrwxrwx 1 root root  41 Mar 27 15:57 privkey.pem -> ../../archive/a3040.com-0001/privkey1.pem

-rw-r--r-- 1 root root 692 Mar 27 15:57 README


  1. spring boot의 내장 서버를 tomcat embed일때 p12파일 만들기
]$ cd /etc/letsencrypt/live/도메인 위치 
]$ openssl pkcs12 -export -in cert.pem -inkey privkey.pem -out keystore.p12 -name tomcat


openssl이 있을 경우 실행되면서

암호를 두번 물어본후 alias를 tomcat으로 keystore.p12라는 파일이 생성됩니다. 톰켓에서 인증서 설치에 사용됩니다.


  1. Spring Boot 애플리케이션 설정 변경하기 application.properties 에 추가


server.ssl.key-store-type=PKCS12
server.ssl.key-store=file:/var/html/keystore.p12
server.ssl.key-store-password=changeit  #p12만들때 입력한 암호
server.ssl.key-alias


만들어진 p12파일을 boot.jar파일 이 있는 곳으로 복사하거나 p12파일이 있는 절대 위치를 기억합니다.


ex) /etc/letsencrypt/live/도메인 위치/keystore.p12 openssl로 만든 그자리 그대로 인경우.

ex) cp /etc/letsencrypt/live/도메인 위치/keystore.p12 /var/html/keystore.p12

만약 /var/html/ 에 boot.jar가 있는 경우.


  1. boot.jar 재시작