시작이 반

[Spring] 스프링 시큐리티 Authentication 바꿔주기 본문

Programming/Spring

[Spring] 스프링 시큐리티 Authentication 바꿔주기

G_Gi 2021. 2. 17. 19:57
SMALL

공부한 내용이므로 틀린 내용이 있을 수 도있습니다...

 

위의 구조를 코드를 짜면서 이해한 내용이다.

회원 수정을 하면 DB의 값을 변경해야 할 뿐아니라 세션 값도 변경해줘야 한다.

 

회원수정 코드 이다.

ajax로 id, username, password를 가져온다.

    update: function (){
        let data ={
            id:$("#id").val(),
            username:$("#username").val(),
            password:$("#password").val()
        }

        $.ajax({
            type:"PUT",
            url:"/user",
            data:JSON.stringify(data), //object -> json
            contentType:"application/json; charset=utf-8",
            dataType:"json"
        }).done(function (response){
            alert("회원 수정 완료");
            location.href = "/";
        }).fail(function (error){
            alert(error);
            alert("회원 수정 실패");
        }); //ajax통신으로 데이터를 json으로 변경 후 insert

    }
    @PutMapping("/user")
    public ResponseDto<Integer> update(@RequestBody User user){
        userService.userModify(user);
        //DB값만 바뀌고 세션값은 바뀌지 않음
        //세션값을 바꿔줘야함

        return new ResponseDto<Integer>(HttpStatus.OK.value(), 1);
    }

 

 

    @Transactional
    public void userModify(User user) {
        //수정시에는 영속성 컨텍스트 User 오브젝트를 영속화 시키고, 영속화된 User 오브젝트를 수정
        //select를 해서 user오브젝트를 DB로부터 가져오는 이유는 영속화를 하기 위해서
        //영속화된 오브젝트를 변경하면 자동으로 DB에 update문을 날림
        User persistance = userRepository.findById(user.getId()).orElseThrow(()->{
            return new IllegalArgumentException("회원찾기 실패");
        });

        String encPassword = bCryptPasswordEncoder.encode(user.getPassword());
        persistance.setPassword(encPassword);

        //세션 등록
        Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);

        //회원수정 합수 종료 = 서비스 종료 = 트랜잭션 종료 = commit 자동으로 됨
        //영속화된 persistance 객체의 변화가 감지되면 더티체킹이 되어 update문을 날림
    }

DB의 값을 바꿔주면서 세션을 새로 등록해준다.

 //세션 등록
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);

새로운 UsernamePasswordAuthenticationToken을 만들어주고 AuthenticationManager을 사용하여 등록을 해준다.

SecurityContextHolder의 안에있는 Context를 불러오고 안에있는 Authentication을 설정해준다.

 

 

여기서 AuthenticationManager을 사용하기위해서는 Bean으로 등록을 해줘야한다.

package Social.Sociallogin.config;

import Social.Sociallogin.config.auth.PrincipalDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;


@EnableWebSecurity //시큐리티 필터가 등록
@EnableGlobalMethodSecurity(prePostEnabled = true) //특정 주소로 접근을 하면 권한 및 인증을 미리 체크
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private PrincipalDetailService principalDetailService;

    @Autowired
    public SecurityConfig(PrincipalDetailService principalDetailService) {
        this.principalDetailService = principalDetailService;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public BCryptPasswordEncoder encodePWD(){ //암호화
        return new BCryptPasswordEncoder();
    }

    // 시큐리티가 대신 로그인해주는데 password를 가로채는데
    // 해당 password가 뭘로 해쉬화해서 회원가입이 되었는지 알아야
    // 같은 해쉬로 암호화해서 DB에 있는 해쉬랑 비교가능
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(principalDetailService).passwordEncoder(encodePWD());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()//csrf토큰 비활성화(테스트시 걸어두는게 좋음)
                    .authorizeRequests()
                    .antMatchers("/","/auth/**","/js/**","/css/**","/image/**") //접근 허용
                    .permitAll()
                    .anyRequest()
                    .authenticated()
                .and()
                    .formLogin()
                    .loginPage("/auth/loginForm")
                    .loginProcessingUrl("/auth/loginProc")//스프링 시큐리티가 해당 주소로 요청오는 로그인정보를 가로채서 loadUserByName으로 던짐 
                    .defaultSuccessUrl("/"); //정상일떄


        http.sessionManagement()
                .maximumSessions(1)
                .maxSessionsPreventsLogin(false);

    }
}
package Social.Sociallogin.service;

import Social.Sociallogin.domain.User;
import Social.Sociallogin.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    private UserRepository userRepository;
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    private AuthenticationManager authenticationManager;


    @Autowired
    public UserService(UserRepository userRepository, BCryptPasswordEncoder bCryptPasswordEncoder, AuthenticationManager authenticationManager) {
        this.userRepository = userRepository;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.authenticationManager = authenticationManager;
    }

    @Transactional
    public void userModify(User user) {
        //수정시에는 영속성 컨텍스트 User 오브젝트를 영속화 시키고, 영속화된 User 오브젝트를 수정
        //select를 해서 user오브젝트를 DB로부터 가져오는 이유는 영속화를 하기 위해서
        //영속화된 오브젝트를 변경하면 자동으로 DB에 update문을 날림
        User persistance = userRepository.findById(user.getId()).orElseThrow(()->{
            return new IllegalArgumentException("회원찾기 실패");
        });

        String encPassword = bCryptPasswordEncoder.encode(user.getPassword());
        persistance.setPassword(encPassword);

        //세션 등록
        Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);

        //회원수정 합수 종료 = 서비스 종료 = 트랜잭션 종료 = commit 자동으로 됨
        //영속화된 persistance 객체의 변화가 감지되면 더티체킹이 되어 update문을 날림
    }

    //////////전통 로그인///////////
    /*@Transactional(readOnly = true)
    public User login(User user){
        return userRepository.findByUsernameAndPassword(user.getUsername(), user.getPassword());
    }*/


}

 

 

tmdrl5779.tistory.com/72?category=832938

 

[Spring] 스프링 시큐리티 로그인

Spring Security란? Spring Security는 Spring기반의 어플리케이션의 보안(인증과 권한(을 담당하는 프레임워크이다. Spring Security는 Filter기반으로 동작한다. Filter는 Dispatcher Servlet으로 가기전에 적용..

tmdrl5779.tistory.com

 

LIST