묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 시큐리티
@Controller permitAll() 적용방법
@RestController에 매핑된 경로들은 permitAll()이 적용되었지만 @Controller에서 매핑한 경로들은 permitAll() 적용이 되지 않습니다. 자료를 아무리 찾아봐도 알 수 없어서 혹시나 도움이 될까 하는 마음에 글 적어봅니다.
-
미해결스프링 시큐리티
커스텀 provider와 시큐리티의 provider 함께 사용하기
안녕하세요.커스텀 provider와 시큐리티의 provider 함께 사용하는 방법을 도저히 못찾겠습니다. 커스텀 필터와 커스텀 provider를 시큐리티 필터체인에 등록커스텀 필터에서 인증되지 않은 사용자 요청은 http basic 방식으로 인증위 요구사항을 충족시키기 위해서 스프링 시큐리티에서 기본적으로 제공하는 provider 리스트와 커스텀 provider를 providerManager가 갖고 있도록하고 싶은데요.저의 커스텀 provider를 bean으로 등록하면 시큐리티에서 제공되는 모든 provider는 providerManager가 갖고 있지 않더라구요. 그래서 AuthenticationManagerBuilder를 통해서 커스텀 provider를 추가하는 방식으로 했는데도...디버깅 모드에선 커스텀 provider만 등록되 상태입니다... 어떻게해야할까요?? @Component 로 빈으로 등록한 커스텀 provider를 주입받고 해당 provider를 authenticationManagerBuilder.authenticationProvider(this.authenticationProvider); 를 통해 추가만 하려고했습니다.... 고견부탁드립니다.. 해결이 안됩니다!!ㅜㅜ @Configuration public class SecurityConfiguration { private static final String CLIENT_ID_HEADER_NAME = "X-CLIENT-ID"; private static final String API_KEY_HEADER_NAME = "X-API-KEY"; private final AuthenticationProvider authenticationProvider; public SecurityConfiguration(AuthenticationProvider authenticationProvider) { this.authenticationProvider = authenticationProvider; } @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class); authenticationManagerBuilder.authenticationProvider(this.authenticationProvider); http.csrf(CsrfConfigurer::disable) .cors(CorsConfigurer::disable) .formLogin(FormLoginConfigurer::disable) .httpBasic(Customizer.withDefaults()); http.authorizeHttpRequests(request -> request.anyRequest().authenticated()); http.addFilterAfter(requestHeaderAuthenticationFilter(http), HeaderWriterFilter.class); return http.build(); } @Bean RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter(HttpSecurity http) throws Exception { RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter(); filter.setPrincipalRequestHeader(CLIENT_ID_HEADER_NAME); filter.setCredentialsRequestHeader(API_KEY_HEADER_NAME); filter.setExceptionIfHeaderMissing(false); filter.setAuthenticationManager(authenticationManager(http)); return filter; } @Bean AuthenticationManager authenticationManager(HttpSecurity http) throws Exception { AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class); return authenticationManagerBuilder.build(); } @Bean InMemoryUserDetailsManager inMemoryUserDetailsManager() { UserDetails admin = User.withUsername("admin").password("admin").build(); return new InMemoryUserDetailsManager(admin); } }
-
미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
Post에 edit 메서드 삼항연산자 질문
업데이트 관련 질문입니다!!PostEdit을 만들고 Post에 edit이라는 메서드를 만들어서 PostEdit자체를 받은 후에 삼항연산자를 쓰는 방식으로 해결해도 문제가 없을까요??@Data public class PostEdit { @NotBlank(message = "제목을 입력하세요.") private String title; @NotBlank(message = "내용을 입력하세요.") private String content; @Builder public PostEdit(String title, String content) { this.title = title; this.content = content; } }public void edit(PostEdit postEdit) { this.title = postEdit.getTitle() != null ? postEdit.getTitle() : this.title; this.content = postEdit.getContent() != null ? postEdit.getContent() : this.content; }
-
미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
@Configuration WebMvcConfig클래스에대해
WebMvcConfig 클래스에 @Configuration애노테이션을 사용하면 addInterceptors 메서드에 @Bean을 달아줘야 동작할줄 알았는데 @Bean 애노테이션을 안달아줘도 잘 작동하는 이유가 궁금합니다.
-
미해결[초급] 찍어먹자! 코틀린과 Spring Security + JWT로 회원가입 만들기
테이블 create문
회원가입 하는데 java.sql.SQLSyntaxErrorException: (conn=90) Unknown SEQUENCE: 'member_seq' 이 오류 때문에 계속 데이터 입력이 안되는데 테이블 create 문 알려주시거나 key값 설정 어떻게 했는지 알려주세요~!
-
해결됨스프링 프레임워크는 내 손에 [스프1탄]
Spring05 버전에서 이미지를 설정했을 때 권한이 보이지 않습니다
안녕하세요. 강의를 잘 듣고 있습니다.다름이 아니라 Spring05에서 로그인 후에 ( ) 안에 권한이 보여지는 부분의 문제 때문에 질문합니다.초기에 회원가입 후 권한을 설정했을 때는 아래와 같이 권한이 잘 나옵니다.하지만 프로필 사진을 등록하면 그 이후부터는 로그아웃 후 다시 로그인을 해도 권한이 보이지 않습니다. SQL을 확인해 보면 테이블에 권한은 삭제되지 않고 있는데 나오구요...header.jsp에서 권한이 보여지는 부분은 잘 작성된 거 같고 maapper.xml도 정상인 것 같은데 왜 프로필 사진을 등록한 이후에는 권한이 보여지지 않는건지 잘 모르겠습니다ㅠㅠ도움을 부탁드립니다!
-
해결됨스프링 프레임워크는 내 손에 [스프1탄]
스프링 시큐리티 로그인 후 모달창 질문드립니다
(선생님 아래 댓글에 나름대로 해결책 적어놓았습니다!) 선생님 안녕하세요.기존 로그인 방식을 session에서 security로 바꾸면서 로그인에 성공하면 RedirectAttribute를 이용한 모달창 띄워주기는 어떻게 해야 하는지 고민됩니다.시큐리티 내부에서 /login.do 요청을 처리해주니 왠지 시큐리티 내부 필터에 설정을 해줘야 하나? 라는 생각이 듭니다.로그인에 실패하면 시큐리티에서 error를 파라미터를 넘겨주니, 로그인 성공 시 특정 파라미터를 1회성으로 넘겨주는 것이 있을까? 라는 생각도 듭니다.아니면.. 시큐리티로 로그인에 성공하는 순간 url경로를 설정하여 특정 컨트롤러에서 받아줘서 그곳에서 redirect를 해줘야 할까요? 아래의 사진은 기존 로그인 방식에서 RedirectAttributes의 addFlash를 이용한 참고사진입니다.감사합니다!
-
해결됨호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
공용키에 대해서 질문있습니다
HS256 방식을 사용했기 때문에 대칭키일것이고, 단 하나의 공용 private key(secret key)가 존재하는 서버에서만 해당 토큰을 인증(검증)할 수 있는 방식으로 알고 있습니다. 이렇게 되면 다른 서버에서는 해당 토큰을 인증(검증)할 수 없는 것이 맞을까요?이러한 경우 해결 방법으로 RS256 알고리즘을 사용하거나,API Gateway를 사용하는 것이 맞나요?
-
미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
dto 변환
회원가입과 비밀번호 암호화 - 1에 5분 10초 정도 쯤에 dto를 서비스 계층으로 바로 넘기는 것이 안 좋다고 호돌님께서 말씀하셨습니다. 그래서 궁금증을 해결해 보고자 검색을 해봤습니다. 근데 dto를 컨트롤러 계층에서 엔티티로 변환하고 서비스 계층으로 넘겨야한다는 의견도 있고 컨트롤러에서 변환하고 넘기는 것보다 서비스 계층에서 dto를 변환해야 한다는 의견이 있는데 호돌님께서 말씀하신 것이 제가 고민하고 있는 것이 맞는지 알고 싶고 호돌님께서는 왜 dto를 서비스 단에 바로 넘기는 것이 안 좋다고 했는지 궁금합니다.!! 의견이 너무 갈려서 뭐가 맞는 방법인지 헷갈리네요
-
미해결스프링 시큐리티
ajax 구현 부분 작동이 안되서 질문드립니다.
ajax가 아예 진행이 안되서 질문드립니다. springSecurity6, 스프링부트 3.2.1 사용중입니다. 코드는 아래와 같은데 이게 어디서 어디가 틀렸는지를 도저히 모르겠습니다.ajax 전까지 form 방식은 정상적으로 작동하고 있으며,ajax 요청 보낼 시 POST http://localhost:8080/api/loginorg.apache.http.client.ClientProtocolException 이런 에러가 발생합니다. ajax.http 파일은 강의 문서를 다시 다운받아 했으며 postman으로 요청시 이유는 모르겠지만 get 요청으로 처리되고 위의 요청시 아래와 같은 로그 발생합니다 10000자 제한떄문에 댓글로 변경 curl 요청시 아래와 같습니다 10000자 제한떄문에 댓글로 변경 아래 코드에서 csrf disable을 하였음에도 계속 동일한 상태이고 강의 git 코드를 여러 브랜치에서 계속 참고해서 막 섞여있어서 어디서부터 고쳐야될지 전혀 모르겠습니다. 거의 6시간 넘게 헤매고 있는데 전혀 모르겠습니다. 혹시 확인 가능하시면 변경해야될 부분 부탁드립니다. 감사합니다. @Configuration @Slf4j @Order(0) public class AjaxSecurityConfig { @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(authenticationProvider); } @Qualifier("ajaxAuthenticationProvider") @Autowired private AuthenticationProvider authenticationProvider; // 변경된 부분 @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { log.info("여기옴2"); http .authorizeHttpRequests(auth-> auth .requestMatchers("/api/login").permitAll() .anyRequest().authenticated() ); http.exceptionHandling(exceptionHandling -> exceptionHandling .authenticationEntryPoint(new AjaxLoginAuthenticationEntryPoint()) .accessDeniedHandler(ajaxAccessDeniedHandler()) ); http.addFilterBefore(ajaxLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class); http.csrf(csrf -> csrf.disable()); return http.build(); } @Autowired private ObjectMapper objectMapper; @Autowired private AuthenticationConfiguration authenticationConfiguration; @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } @Bean public AuthenticationSuccessHandler ajaxAuthenticationSuccessHandler(){ return new AjaxAuthenticationSuccessHandler(); } @Bean public AuthenticationFailureHandler ajaxAuthenticationFailureHandler(){ return new AjaxAuthenticationFailureHandler(); } public AccessDeniedHandler ajaxAccessDeniedHandler() { return new AjaxAccessDeniedHandler(); } @Bean public AjaxLoginProcessingFilter ajaxLoginProcessingFilter() throws Exception { AjaxLoginProcessingFilter filter = new AjaxLoginProcessingFilter(); filter.setAuthenticationManager(authenticationManager(authenticationConfiguration)); filter.setAuthenticationSuccessHandler(ajaxAuthenticationSuccessHandler()); filter.setAuthenticationFailureHandler(ajaxAuthenticationFailureHandler()); return filter; } // @Bean // public AjaxLoginProcessingFilter ajaxLoginProcessingFilter(){ // AjaxLoginProcessingFilter ajaxLoginProcessingFilter = new AjaxLoginProcessingFilter(); // ajaxLoginProcessingFilter.setAuthenticationManager(authenticationManagerBean()); // return ajaxLoginProcessingFilter; // } } @Slf4j @Component public class AjaxAuthenticationProvider implements AuthenticationProvider { @Autowired private UserDetailsService userDetailsService; @Autowired private PasswordEncoder passwordEncoder; /** * 검증에 대한 구현 부분 * * 여기서 전달받는 authentication 객체는 AuthenticationManager에서 전달받는 것 * @param authentication the authentication request object. * @return * @throws AuthenticationException */ @Transactional @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password = (String) authentication.getCredentials(); log.info("ajax Authentication"+ authentication); log.info("ajax username : "+username); log.info("ajax password : "+password); /** * db에 있는 사용자를 가져오는 부분 */ AccountContext accountContext = (AccountContext)userDetailsService.loadUserByUsername(username); if (!passwordEncoder.matches(password, accountContext.getPassword())){ throw new BadCredentialsException("ajax invalid password!"); } /** * 섹션 4-8에서 secret key 추가해서 검증하는 부분 */ // FormWebAuthenticationDetails formWebAuthenticationDetails = (FormWebAuthenticationDetails) authentication.getDetails(); // String secretKey = formWebAuthenticationDetails.getSecretKey(); // // if (secretKey == null || !"secret123".equals(secretKey)){ // throw new InsufficientAuthenticationException("secret key invalid"); // } AjaxAuthenticationToken authenticationToken = new AjaxAuthenticationToken(accountContext.getAccount(),null,accountContext.getAuthorities()); // log.info(""+accountContext.getAccount()); // log.info(""+authenticationToken); return authenticationToken; } /** * parameter 로 전달되는 authentication 타입과 여기서 검증하려는 대상의 타입이 일치하면 검증하도록 하는거 * @param authentication * @return */ @Override public boolean supports(Class<?> authentication) { return authentication.equals(AjaxAuthenticationToken.class); } } public class AjaxAuthenticationToken extends AbstractAuthenticationToken { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private final Object principal; private Object credentials; /** * 인증받기전에 사용자가 입력한 아이디와 비밀번호 담는 생성자 * */ public AjaxAuthenticationToken(Object principal, Object credentials) { super(null); this.principal = principal; this.credentials = credentials; setAuthenticated(false); } /** * 여기는 인증 완료후 아이디와 비번, 권한정보를 담는 생성자 */ public AjaxAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) { super(authorities); this.principal = principal; this.credentials = credentials; super.setAuthenticated(true); // must use super, as we override } public static UsernamePasswordAuthenticationToken unauthenticated(Object principal, Object credentials) { return new UsernamePasswordAuthenticationToken(principal, credentials); } public static UsernamePasswordAuthenticationToken authenticated(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) { return new UsernamePasswordAuthenticationToken(principal, credentials, authorities); } @Override public Object getCredentials() { return this.credentials; } @Override public Object getPrincipal() { return this.principal; } @Override public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { Assert.isTrue(!isAuthenticated, "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); super.setAuthenticated(false); } @Override public void eraseCredentials() { super.eraseCredentials(); this.credentials = null; } } @Slf4j public class AjaxLoginProcessingFilter extends AbstractAuthenticationProcessingFilter { private ObjectMapper objectMapper = new ObjectMapper(); private static final String XML_HTTP_REQUEST = "XMLHttpRequest"; private static final String X_REQUESTED_WITH = "X-Requested-With"; public AjaxLoginProcessingFilter() { /** * 여기서 정한 경로의 요청만 받음 * 여기서 path 가 일치해야만 수행함 */ super(new AntPathRequestMatcher("/login", "POST")); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { log.info("isAjax processing"); if (isAjax(request)){ throw new IllegalStateException("Authentication is not supported"); } AccountDto accountDto = objectMapper.readValue(request.getReader(), AccountDto.class); /** * accountDto 비어있는지 확인하는 부분인데 StringUtils.isEmpty 가 deprecated 되어서 ObjectUtils.isEmpty 사용 */ if (ObjectUtils.isEmpty(accountDto.getUsername()) || ObjectUtils.isEmpty(accountDto.getPassword())){ throw new AuthenticationServiceException("Username op Password is empty"); } AjaxAuthenticationToken token = new AjaxAuthenticationToken(accountDto.getUsername(), accountDto.getPassword()); return this.getAuthenticationManager().authenticate(token); } /** * 클라이언트와 약속 정해서 * 그게 참이면 ajax 요청이 맞다고 판단함 * @param request * @return */ private boolean isAjax(HttpServletRequest request) { return "XMLHttpRequest".equals(request.getHeader("X-Requested-With")); } }
-
미해결스프링부트 시큐리티 & JWT 강의
JWT - 24강 authenticationManager() 문제 해결책
버전 문제로 authenticationManager() 안되면 SecurityConfig @Configuration @RequiredArgsConstructor @EnableWebSecurity // 스프링 시큐리티 필터가 스프링 필터체인에 등록된다. public class SecurityConfig { private final CorsConfig corsConfig; // private final CorsFilter corsFilter; // Bean 으로 등록되어 있어서 바로 가져다 써도됨 근데 나는 걍 위에 클래스에서 메소드 호출할거임~ @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); // http.addFilterBefore(new MyFilter3(), SecurityContextHolderFilter.class); http.csrf(CsrfConfigurer::disable); // http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.sessionManagement((sessionManagement) -> sessionManagement .sessionCreationPolicy(SessionCreationPolicy.STATELESS)); http.addFilter(corsConfig.corsFilter()); // @CrossOrigin(인증X), 시큐리티 필터에 등록인증(O) // http.formLogin().disable(); http.formLogin((form)-> form.disable()); // http.httpBasic().disable(); http.httpBasic((basic)-> basic.disable()); http.addFilter(new JwtAuthenticationFilter(authenticationManager)); // AuthenticationManger http.authorizeHttpRequests(authorize -> authorize.requestMatchers("/user/**").authenticated() .requestMatchers("/manager/**").hasAnyRole("ADMIN", "MANAGER") .requestMatchers("/admin/**") .hasAnyRole("ADMIN").anyRequest().permitAll()); return http.build(); } } JwtAuthenticationFilter // 스프링 시큐리티에서 UsernamePasswordAuthenticationFilter 가 있음 // /login 요청해서 username, password 전송하면 (post) // UserPasswordAuthenticationFilter가 동작을 함 @RequiredArgsConstructor public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final AuthenticationManager authenticationManager; // /login 요청을 하면 로그인 시도를 위해서 실행되는 함수 @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { System.out.println("로그인 시도: JwtAuthenticationFilter"); return super.attemptAuthentication(request, response); } }
-
미해결스프링 프레임워크는 내 손에 [스프1탄]
아이디 중복확인 NullPointerException
20:35 예시 코드처럼 입력했는데, 공백을 입력하고 중복확인을 하는 경우처럼 반환되는 Member가 없는 경우 NullPointerException이 발생합니다. memID로 찾아지는 Member가 있는 경우 0을 반환하면서 잘 동작합니다.선생님 예시에서는 작동이 잘 되는데 왜 저는 안 되는 걸까요? 옵셔널이나 예외처리를 해주어야 할까요? @RequestMapping("/memRegisterCheck.do") public @ResponseBody int memRegisterCheck(@RequestParam("memID") String memID) { //넘어오는 파라미터 이름과 받는 이름이 같은 경우 생략 가능 Member m = memberMapper.registerCheck(memID); if (m != null || m.equals("")) { //아이디가 중복이거나 공백인 경우 => 사용불가 return 0; } return 1; //사용 가능 } java.lang.NullPointerException kr.board.controller.MemberController.memRegisterCheck(MemberController.java:25) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:871) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:777) org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:870) javax.servlet.http.HttpServlet.service(HttpServlet.java:489) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855) javax.servlet.http.HttpServlet.service(HttpServlet.java:583) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
-
미해결스프링부트 시큐리티 & JWT 강의
권한 설정 부여가 안됨
@Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ http.csrf(CsrfConfigurer::disable); http.authorizeHttpRequests(authorize -> authorize // "/user/~" 이 주소로 들어오면 인증이 필요함 -> 인증만 되면 들어갈 수 있는 주소! .requestMatchers("/user/**").authenticated() // "/manager/~" 이 주소로 들어가기 위해서는 Admin과 Manager 권한이 있는 사람만 들어올 수 있음 .requestMatchers("/manager/**").hasAnyRole(Role.ADMIN.name(), Role.MANAGER.name()) // "/admin/**" 이 주소로 들어가기 위해서는 Admin 권한이 있는 사람만 들어올 수 있음 .requestMatchers("/admin/**").hasAnyRole(Role.ADMIN.name()) // 설정한 주소가 아니면 누구나 들어갈 수 있음 .anyRequest().permitAll() );enum을 사용하여 Spring Security를 다음과 같이 설정했습니다. public enum Role { USER, MANAGER, ADMIN } enum은 다음과 같이 작성했습니다. DB는 다음과 같습니다. 문제가 없는 것 같은데.. /admin 또는 /manager로 들어갈 시에 403에러가 뜹니다. 시큐리티 설정에서 문자열로 바꾸거나 ROLE_ 붙여도 안되고... 현재 쓰고있는 버전은 스프링 3.X버전, 시큐리티 6.X버전입니다.에러가 나는 이유가 무엇일까요?
-
미해결스프링부트 시큐리티 & JWT 강의
코틀린 시큐리티 컨피그 설정방법 참고하세요
코틀린에서 이번강의 설정할땐 import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration 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.configurers.CsrfConfigurer import org.springframework.security.web.SecurityFilterChain @Configuration @EnableWebSecurity class SecurityConfig { @Bean fun filterChain(http:HttpSecurity):SecurityFilterChain{ http.csrf(CsrfConfigurer<HttpSecurity>::disable) http.authorizeHttpRequests{ it.requestMatchers("/user/**").authenticated() it.requestMatchers("/manager/**").hasAnyRole("MANAGER","ADMIN") it.requestMatchers("/admin/**").hasRole("ADMIN") it.anyRequest().permitAll() } http.formLogin{ it.loginPage("/login") it.permitAll() } return http.build() } } 이런식으로 하시면됩니다WebSecurityConfigurerAdapter는 사라졌고 대신 빈을 생성해서 등록하는식으로 바뀐거같고기본적으로 직렬로 메서드체이닝하던게 다 람다식으로 빠졌고(자기자신을 설정하는건 다 내부람다식으로 동작하게 바뀐듯)authorizeRequests->authorizeHttpRequestsantMatcher->requestMatchersand().formLogin()->http.formLogin{...}이렇게 이름이 변경된친구들도 있습니다
-
미해결스프링부트 시큐리티 & JWT 강의
배달의 민족 모티브로한 프로젝트 중 질문..
안녕하세요 강사님!사장 테이블과 사용자 테이블을 나누었을 경우 강의에서는 PrincipatDetails()나 PrincipalDetailsService()에서는 Member를 컴포지션 하고 있는데요1. 테이블을 나누었을 경우 MemberDetails,OwnerDetails등 각각 따로 만들어줘야하나요?2. 만약 따로 만들어줘야 하면 로그인 요청이 오면 JwtAuthenticationFilter.attemptAuthentication()가 실행되고 PrincipalDetailsService()가 실행될텐데. 여기서 사장이 로그인 했을 경우와 사용자가 로그인 했을 경우 아이디가 같을 경우 에는 어떻게 처리하면 좋을까요?..3. 아니면 한 테이블에서 관리하는게 좋을까요?제가 생각했을 때는 테이블을 사장과 사용자와 합칠 경우에는 가게 테이블과 연관관계 매핑을 하기가 힘들다고 생각했었습니다. 회원은 여러개의 가게를 가질수 있다? 미숙한 질문이지만 답변 부탁드릴게요 !!
-
미해결스프링 시큐리티
depracated된것들이 너무 많습니다 ㅠㅠ
신입 개발자로서 현업을 하며 security에 대해 실력을 키우고자 하여 강의를 듣고 있습니다. 그런데 기술중에 deprecated 된 기술들이 너무 많아 따라가는데 시간이 너무 많이 소요되는거 같습니다... 이것을 해결하기 위해 최신화 된 Git 레포지 주소나 해결 방안 같은것을 자막식으로 달아주실수 있을까요..?아니면 버전을 다운그레이드해서 들어야하나요,,,?ㅜㅜ
-
미해결스프링 시큐리티
스프링 시큐리티 주요 아키텍처 이해 - 4. 인증 저장소 관련 질문
안녕하세요. Spring Security 강의에서 스프링 시큐리티 주요 아키텍처 이해 - 4. 인증 저장소 강의를 듣던 중 SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); 위를 설정하여 자식 쓰레드도 동일한 Security Context를 공유하는 부분에 대해서 실습하던 중 아래와 같이 코드를 작성했는데 아무리 실행해도 계속 thread가 실행되는 컨트롤러에서 authentication 객체가 null 값을 가지는 것을 확인했습니다. "/" 가 실행되는 index 메소드에서 String strategy = SecurityContextHolder.getContextHolderStrategy().getClass().getSimpleName();System.out.println("strategy = " + strategy); 위를 통해서 출력 결과를 확인했을 때 "ThreadLocalSecurityContextHolderStrategy" 값이 나오는 것을 확인했습니다. 제가 판단하기로는 적용이 안 된 결과로 보였는데요 어느 시점에 setStrategyName를 적용해줘야 적용이 되는지 잘 모르겠습니다. 아래는 소스 코드 입니다.[SecurityCofnig]package io.security.basicsecurity;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.Customizer;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.web.SecurityFilterChain;@Configuration@EnableWebSecuritypublic class SecurityConfig4 {@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(auth -> {auth.anyRequest().authenticated(); }); http.formLogin(Customizer.withDefaults()); SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); return http.build(); }} [Controller]package io.security.basicsecurity;import jakarta.servlet.http.HttpSession;import org.springframework.security.core.Authentication;import org.springframework.security.core.context.SecurityContext;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.web.context.HttpSessionSecurityContextRepository;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class SecurityController {@GetMapping("/")public String index(HttpSession session) {String strategy = SecurityContextHolder.getContextHolderStrategy().getClass().getSimpleName(); System.out.println("strategy = " + strategy); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); SecurityContext context = (SecurityContext) session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY); Authentication authentication1 = context.getAuthentication(); System.out.println("무슨 값? " + authentication1.toString()); return "home"; }@GetMapping("/thread")public String thread() {new Thread(new Runnable() {@Override public void run() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if(authentication == null) {System.out.println("Null 값임"); }}}).start(); return "thread"; }
-
해결됨스프링 시큐리티
최신 spring security 기준 web.ignoring 관련 질문입니다
현재 최신 spring security 및 spring 3.2.1 버전을 사용중입니다.강의 섹션 3-2번강의에서 web.ignoring 설정이 현재 SecurityFilterChain에는 어떻게 적용해야 될지 몰라 찾아보던 중 아래와 같은 자료를 발견하였습니다.해당 자료는 spring security 관련https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html#favor-permitall위의 주소에서 확인하였는데 이부분과 관련하여 질문드립니다. 최신 버전에서는 위의 사진과 같이 코드를 사용하는게 좋을까요? 만약 위와 같이 사용한다면 달라지는 부분이 있는지 궁금하여 질문드립니다. 현재 제가 작성한 코드는 아래와 같습니다.추가한 부분은 css, js, img, favcon.ico, webjars 입니다http .authorizeHttpRequests(Authorize -> Authorize .requestMatchers("/mypage").hasRole("USER") .requestMatchers("/messages").hasRole("MANAGER") .requestMatchers("/config").hasRole("ADMIN") .requestMatchers("/css/**").permitAll() .requestMatchers("/js/**").permitAll() .requestMatchers("/img/**").permitAll() .requestMatchers("/favcon.ico").permitAll() .requestMatchers("/webjars").permitAll() .requestMatchers("/").permitAll() .anyRequest().authenticated() );전체 부분 @Configuration @EnableWebSecurity @Slf4j public class SecurityConfig{ @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("user").password(new BCryptPasswordEncoder().encode("1111")).roles("USER"); auth.inMemoryAuthentication().withUser("manager").password(new BCryptPasswordEncoder().encode("1111")).roles("MANAGER","USER"); auth.inMemoryAuthentication().withUser("admin").password(new BCryptPasswordEncoder().encode("1111")).roles("ADMIN","MANAGER","USER"); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(Authorize -> Authorize .requestMatchers("/mypage").hasRole("USER") .requestMatchers("/messages").hasRole("MANAGER") .requestMatchers("/config").hasRole("ADMIN") .requestMatchers("/css/**").permitAll() .requestMatchers("/js/**").permitAll() .requestMatchers("/img/**").permitAll() .requestMatchers("/favcon.ico").permitAll() .requestMatchers("/webjars").permitAll() .requestMatchers("/").permitAll() .anyRequest().authenticated() ); http.formLogin( formLogin -> formLogin .successHandler(new AuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { RequestCache requestCache = new HttpSessionRequestCache(); // 이걸 이용해 세션에 원래 가고자 하는 경로 저장되어 있음 SavedRequest savedRequest = requestCache.getRequest(request, response); //여기에 저장되어있음 String redirectUrl = savedRequest.getRedirectUrl(); log.info("redirectUrl : " + redirectUrl); response.sendRedirect(redirectUrl); } }) .permitAll() ); http .csrf(csrf -> csrf. csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) ); return http.build(); } }
-
미해결스프링부트 시큐리티 & JWT 강의
jwt에 관해 질문이 있습니다.
좋은 강의 감사합니다.강의를 모두 들었는데 궁금점이 생겨서 질문을 남기게 되었습니다.1. postman으로 했을 때에는 JSON 타입으로 값을 넣어주고 이후의 요청에서는 헤더에 있는 토큰을 직접 넣어줬었는데 실제 웹에서 요청할 때에는 postman처럼 헤더를 넣지 못하니까 자동으로 넣어지게 되나요?아니면 이거에 관련한 코드나 설정이 추가로 필요한가요?2. 이전의 시큐리티에서 세션을 사용해서 OAuth 코드랑 jwt에서의 OAuth 코드는 다르다 하셨는데 jwt를 쓸 때에는 OAuth를 사용하지 않는 편인가요?아니라면 세션과 약간 다르기는 하지만 비슷하게 코드를 짜면 jwt 로그인과 OAuth를 같이 사용할 수 있는지 궁금합니다!
-
미해결스프링부트 시큐리티 & JWT 강의
로그인 방식에 대해서 궁금한게 있습니다!
안녕하세요 유튜브 메타코딩 시절부터 즐겨봤는데 인프런에서도 보니 반갑네요! ㅎㅎ 다름이 아닌 로그인 방식에 대해서 궁금하게 생겨서 질문 드립니다.현재 프로젝트에서 로그인 방식은프론트에서 아이디와 비밀번호를 전송함Controller에서 아이디와 비밀번호를 받아 Service단에서 로그인 로직을 돌며 DB와 비교하여 로그인의 성공 유무를 알려줌 (성공시 JWT 제공) (정해진 JSON 형식대로 DTO에 담아 프론트에 제공)그 후 요청마다 JWT를 JWTAuthenticationFilter에서 인증함. 그런데 문득 강의를 듣다보니 로그인 방식을 굳이 Service 단으로 가져가지 않고 필터단에서 처리하는게 더 괜찮은 방식이며 Spring Security를 더 적절히 사용하는게 아닐까라는 생각이 들었습니다.이렇게 된다면 사용자가 입력한 아이디와 비밀번호를 Custom 필터에서 로그인을 진행하게 되겠네요. 하지만 이렇게 될 경우 현재 프로젝트에서 사용하는 로그인 방식과는 다르게 DTO에 담지 못하니 직접 response에 현재 정해진 JSON 형식대로 만들어 보내주는 방법밖에 없을거 같은데 이러한 방식이 주로 사용되는 방식일까요?!