묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결이거 하나로 종결-스프링 기반 풀스택 웹개발 무료강의
다운로드 불가
1강 소개 자료 zip 파일이 압축 해제가 안 됩니다!
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
다음강의는뭐에요?
동시성준비중이신다음강의는뭐에요?
-
미해결스프링 프레임워크는 내 손에 [스프1탄]
lombok api 등록 후
lombok을 임포트시키고 나서 아웃라인에 변화가 일어나지 않습니다.이런 경고메시지도 떴는데 뭐가 잘못된 걸까요..?
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
Samesite를 더 공부 해보고 싶습니다.
안녕하세요. 선생님시큐리티 강의를 재밌게 듣고있는 한 학생으로서 명품강의를 만들어주셔서 감사드립니다. 강의를 들으면서 SameOrigin과 쿠키(SameSite)의 차이를 구별할 수 있게 됐고 더 나아가 Samesite간의 SingleSignOn(sso)이라는 기술도 관심을 갖게 됐습니다. sso관련하여 추천하실만한 도서나 기술블로그가 있으신지 궁금합니다~!
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
로그인
로그인의 경우 앞선강의에서 /login 엔드포인트로 post요청을 보낼텐데, 지금 예제를 보면 모든 엔드포인트에 대하여 HttpMethod.POST는 ROLE_WRITE권한을 가져야한다라고 명시되어져 있습니다.MANAGER권한을 갖은 UserDetails 계정으로 로그인을하면 post요청을 보내니 로그인이 실패되지 않을까 고민이 되었는데, 성공하는 것을 강의에서 확인하였습니다. 이것이 왜 가능한 것인지 궁금합니다.
-
해결됨호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
querydsl Q class 이슈
plugins { id 'java' id 'org.springframework.boot' version '3.0.5' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id "org.asciidoctor.jvm.convert" version "3.3.2" } group = 'org.spring' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } asciidoctorExt } repositories { mavenCentral() } ext { snippetsDir = file('build/generated-snippets') } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.security:spring-security-crypto' implementation 'org.springframework.session:spring-session-jdbc' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.security:spring-security-test' implementation 'org.bouncycastle:bcprov-jdk15on:1.70' implementation 'com.querydsl:querydsl-core:5.0.0' implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" annotationProcessor 'jakarta.persistence:jakarta.persistence-api' annotationProcessor 'jakarta.annotation:jakarta.annotation-api' implementation 'io.jsonwebtoken:jjwt-api:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" asciidoctorExt "org.springframework.restdocs:spring-restdocs-asciidoctor:3.0.0" testImplementation "org.springframework.restdocs:spring-restdocs-mockmvc:3.0.0" annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testCompileOnly "org.projectlombok:lombok" testAnnotationProcessor "org.projectlombok:lombok" runtimeOnly 'com.h2database:h2' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'org.modelmapper:modelmapper:3.2.0' } tasks.named('test') { useJUnitPlatform() } test { outputs.dir snippetsDir } asciidoctor { inputs.dir snippetsDir configurations 'asciidoctorExt' dependsOn test } asciidoctor.doFirst { delete file("src/main/resources/static/docs") } bootJar { enabled = true dependsOn asciidoctor copy { from asciidoctor.outputDir into "src/main/resources/static/docs" } } jar { enabled = false } FAILURE: Build failed with an exception.* What went wrong:Execution failed for task ':compileJava'.> Compilation failed; see the compiler error output for details.* Try:> Run with --info option to get more log output.> Run with --scan to get full insights.BUILD FAILED in 6s 안녕하세요querydsl 빌드 후 Q class 임포트 하는 곳에서 에러가 발생합니다 ㅠ구글링해서 이런 저런 방법 찾아서 혼지사 해보려고 했는데 쉽지않네요.. 그 밖에 캐시 지우고 재시작, java SDK 설정, 빌드설정 등 여러가지 방법을 해보았는데 잘 안됩니다 ㅠ두세시간 정도 삽질중인데 도움 좀 주실 수 있을까요..
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
로그인 후 리다이렉트
인증제공자 2에서 커스텀한 필터 적용하고 마지막으로 서버 가동후에 테스트 하는데 해당 화면이 뜹니다.주소창에 localhost:8080 입력후 접근하면 제대로 뜨는 것을 보면 리다이렉트 문제라고 생각되는데쿼리스트링으로 인증 후에 다시 루트로 리다이렉트를 어떻게 해야 하나요?다 옮겨 적은 거 같은데 혹시 제가 놓친 설명이나 코드가 있다면 죄송합니다.
-
미해결스프링부트 시큐리티 & JWT 강의
password 비교를 하지 않았는데 어떻게 인증이 통과된 건가요?
안녕하세요!스프링 시큐리티 다양한 분들 강의를 봤는데 이렇게 핵심만 요약해서 알려주시는 강의는 없었던 것 같습니다. attemptAuthentication 에서 authRequestToken으로 loadUserByUsername 를 호출 후 password 를 비교하는 로직이 없는데 어떻게 successfulAuthentication 으로 넘어가는지 이해가 안됩니다. 어느 시점에 password 를 비교하는지 궁금합니다.
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
스프링 시큐리티 6.0 강의를 구매했는데요. 혹시 이전강의 스프링시큐리티 Auth를 안들어도 괜찮은지 궁금하네요.
스프링 시큐리티 6.0 강의를 구매했는데요. 혹시 이전강의 스프링시큐리티 Auth를 안들어도 괜찮은지 궁금하네요. 인트로 보고 있는데, 이전강의 얘기 하셔서, 혹시 이전강의 봐야만 하는지..
-
미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
Windows WSL Vue 설정
안녕하세요, 호돌님. Windows11 Home Edition 사용 유저입니다. 강의 보면서 Vue 개발 환경 조성 부분에서 막막했는데, 커뮤에 언급하신 WSL로 구글링 하면서 npm dev 서버까지 띄웠습니다. 하루 온종일 구글링 보면서 삽질을 한거라 그냥 날리기는 아깝고 제 방식이 저같은 분들께 도움이 좀 되었으면 해서 정리한 내용 올립니다. https://blog.naver.com/hellom0501/223652563722 다만 WSL의 특성상 윈도우와 마운트 된 파티션에서의 빌드나 npm 작업은 엄청난 속도 저하가 발생합니다.딱히 개선점은 없는 것 같고, WSL2를 WSL1으로 다운 그레이드하면 나아질 것이라고 해서 수정해봤는데 체감되진 않네요.아니면 아예 WSL 내부에서 개발 환경을 구축하고 작업을 하는 수 밖에 없는 것 같습니다. 좋은 강의 감사합니다.
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
AuthenticationManager가 부모 AuthenticationManager를 가지는 이유를 모르겠어요
AuthenticationManager가 부모 AuthenticationManager를 가지는 이유를 모르겠습니다. 매니저는 프로바이더를 여러 개 가질 수 있는데, 굳이 부모 매니저를 추가로 가질 수 있도록 해서 부모의 프로바이더를 사용해야할 이유가 있을까요? 그리고 그렇게 사용하는 적절한 예시가 있을까요?
-
해결됨스프링 시큐리티
[해결 방법] MethodSecurityConfig.customMethodSecurityMetadataSource() 호출하지 않는 이슈
@EnableGlobalMethodSecurity 애노테이션이 설정되어있는 곳 모두 찾아서 주석 처리@Order(0) //@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) @EnableWebSecurity @Configuration public class SecurityConfig2 extends WebSecurityConfigurerAdapter {@Order(1) @Configuration //@EnableGlobalMethodSecurity(securedEnabled = true) @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {
-
미해결[초급] 찍어먹자! 코틀린과 Spring Security + JWT로 회원가입 만들기
unique 작성법
@Table 애노테이션을 써서 unique 를 설정하셨는데,@Column(unique = true) 로 설정하는 방법을 사용하지 않으신 이유가 있나요??
-
해결됨스프링 시큐리티
AbstractSecurityInterceptor.class.beforeInvocation()를 2번 실행하는 경우
@Order(0) @Configuration @EnableWebSecurity public class SecurityConfig2 extends WebSecurityConfigurerAdapter { @Autowired private SecurityResourceService securityResourceService; @Autowired private FormAuthenticationDetailsSource authenticationDetailsSource; @Autowired private AuthenticationSuccessHandler customAuthenticationSuccessHandler; @Autowired private AuthenticationFailureHandler customAuthenticationFailureHandler; private String[] permitAllPattern = {"/", "/login", "/user/login/**"}; @Bean public PermitAllFilter customFilterSecurityInterceptor() throws Exception { PermitAllFilter permitAllFilter = new PermitAllFilter(permitAllPattern); permitAllFilter.setSecurityMetadataSource(urlFilterInvocationSecurityMetadataSource()); permitAllFilter.setAccessDecisionManager(affirmativeBased()); permitAllFilter.setAuthenticationManager(authenticationManagerBean()); return permitAllFilter; } private AccessDecisionManager affirmativeBased() { AffirmativeBased affirmativeBased = new AffirmativeBased(getAccessDecisionVoters()); return affirmativeBased; } private List<AccessDecisionVoter<?>> getAccessDecisionVoters() { List<AccessDecisionVoter<? extends Object>> accessDecisionVoters = new ArrayList<>(); accessDecisionVoters.add(new IpAddressVoter(securityResourceService)); accessDecisionVoters.add(roleVoter()); return accessDecisionVoters; } @Bean public RoleHierarchyVoter roleVoter() { RoleHierarchyVoter roleHierarchyVoter = new RoleHierarchyVoter(roleHierarchy()); return roleHierarchyVoter; } @Bean public RoleHierarchyImpl roleHierarchy() { RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); return roleHierarchy; } @Bean public FilterInvocationSecurityMetadataSource urlFilterInvocationSecurityMetadataSource() throws Exception { return new UrlFilterInvocationSecurityMetadataSource(urlResourcesMapFactoryBean().getObject(), securityResourceService); } private UrlResourcesMapFactoryBean urlResourcesMapFactoryBean() { UrlResourcesMapFactoryBean urlResourcesMapFactoryBean = new UrlResourcesMapFactoryBean(); urlResourcesMapFactoryBean.setSecurityResourceService(securityResourceService); return urlResourcesMapFactoryBean; } @Bean public AuthenticationProvider authenticationProvider() { return new FormAuthenticationProvider(passwordEncoder()); } @Bean public AccessDeniedHandler accessDeniedHandler() { CustomAccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler(); accessDeniedHandler.setErrorPage("/denied"); return accessDeniedHandler; } @Bean public AuthenticationSuccessHandler ajaxAuthenticationSuccessHandler() { return new AjaxAuthenticationSuccessHandler(); } @Bean public AuthenticationFailureHandler ajaxAuthenticationFailureHandler() { return new AjaxAuthenticationFailureHandler(); } @Bean public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(AuthenticationManagerBuilder auth) { auth.authenticationProvider(authenticationProvider()); } @Override public void configure(WebSecurity web) { web.ignoring() .requestMatchers(PathRequest.toStaticResources() .atCommonLocations()); } @Override protected void configure(final HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/mypage").hasRole("USER") .antMatchers("/messages").hasRole("MANAGER") .antMatchers("/config").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .loginProcessingUrl("/login_proc") .authenticationDetailsSource(authenticationDetailsSource) .successHandler(customAuthenticationSuccessHandler) .failureHandler(customAuthenticationFailureHandler) .permitAll() ; http.exceptionHandling() .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")) .accessDeniedPage("/denied") .accessDeniedHandler(accessDeniedHandler()) .and() .addFilterBefore(customFilterSecurityInterceptor(), FilterSecurityInterceptor.class) ; http.csrf() .disable(); customConfigurer(http); } private void customConfigurer(HttpSecurity http) throws Exception { http.apply(new AjaxLoginConfigurer<>()) .successHandlerAjax(ajaxAuthenticationSuccessHandler()) .failureHandlerAjax(ajaxAuthenticationFailureHandler()) .setAuthenticationManager(authenticationManagerBean()) .loginProcessingUrl("/api/login"); } }
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
Custom DSLs 뜻
DSLs 검색해보니 도메인 특화 언어로 주로 나오던데 해당 뜻으로 사용되는게 맞는지 궁금합니다 ㅎ
-
미해결스프링 시큐리티
강의 코드가 왜이렇게 뒤죽박죽인가요...
7) Ajax 로그인 구현 & CSRF 설정에서 그 다음으로 코드를 수정하는 챕터는 지금 이 파트인거 같은데 갑자기 SecurityConfig 클래스에 customConfigurer, ajaxAuthenticationProvider, ajaxAuthenticationSuccessHandler, ajaxAuthenticationFailureHandler 메서드가 왜 있는건가요.. 하.. 이게 한 두개 챕터면 그냥 실수라고 생각하지만 지금 10챕터 이상이 이렇게 수정하면서 진행하는데 강의 이해도도 떨어지고 시간도 다 잡아먹고 뭐하는건지 모르겠습니다.. 아무리 리팩토링하셨다고 말씀하셨더라도 그럼 리팩토링한 영상을 새로 올리시거나 아니시면 리팩토링 전으로 강의가 흘러가야되는거 아닌가요...답답해서 참다가 글 남깁니다..
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
기억하기 인증 필터(RememberMeAuthenticationFilter) 강의를 듣다가 사소한 궁금증이 생겨 질문드립니다.
안녕하세요.기억하기 인증 필터(RememberMeAuthenticationFilter) 강의를 듣다가 사소한 궁금증이 생겨 질문드립니다. 리멤버미 쿠키를 사용시 쿠키를 바탕으로 인증 정보를 가져오는 로직에서, JSESSIONID 쿠키가 만료되었을 때와 서버가 재시작되었을 때 password가 왜 다르게 불러와지는지 알고 싶습니다. 서버 재시작 시 리멤버미 쿠키로 인증 정보가 복구되지 않는 이유를 조사하던 중에 생긴 의문인데요. 제 생각으로는 쿠키에 인증 정보를 담고 있어서, 서버가 재시작되더라도 쿠키가 만료되지 않는 한 인증 정보를 복구할 수 있을 것 같았거든요. 제가 코드를 따라가서 확인한 부분은..리멤버미 쿠키를 생성할때 맨 마지막 필드로 makeTokenSignature 메서드의 값이 들어가는데 이 값은 String data = username + ":" + tokenExpiryTime + ":" + password + ":" + getKey(); 정보를 조합하여 만들어지는데,여기서 getKey()는 RememberMeConfigurer에서 init할때 rememberMeServices를 커스텀하게 주입하지 않으면RememberMeConfigurer에서 UUID.randomUUID().toString()로 가져오기 때문에 서버가 재시작할때마다 랜덤한 값을 가지고 오더라구요. 그래서 서버가 재시작되더라도 고정된 key값을 사용하기 위해 TokenBasedRememberMeService를 생성하여 아래와 같이 설정하였습니다.이후에 getKey()할때도 key로 test를 가지고 오는것을 확인하였구요. 그러면 이제 key가 고정이기 때문에 서버가 재시작되어도 리멤버미 쿠키를 바탕으로 인증을 진행하여 로그인 없이 세션이 유지될줄 알았는데?!, processAutoLoginCookie 메서드에서 아래 코드에서 exception이 발생합니다.. if (!equals(expectedTokenSignature, actualTokenSignature)) { throw new InvalidCookieException("Cookie contained signature '" + actualTokenSignature + "' but expected '" + expectedTokenSignature + "'"); } 확인해보니 유저 정보를 가져올때 password를 다르게 가져오고있더라구요. TokenSignature는 password와 여러 정보를 조합하여 만드는데, password값이 달라지니 예상값과 실제값이 차이가 나서 exception이 떨어지구요.. UserDetails userDetails = getUserDetailsService().loadUserByUsername(cookieTokens[0]);*로그인 > JSESSIONID 삭제 이후 로그인시*서버 재시작 이후 로그인시 질문이 좀 장황했는데, 왜 password를 다르게 가져오는지 궁금합니다. 코드를 쫓아가다가 길을 잃어서 도움을 받을수 있을까 하여 질문을 남겨요.. 감사합니다.
-
미해결스프링부트 시큐리티 & JWT 강의
이전 강의 참고하라는 말씀
안녕하세요! 최주호 강사님의 수준높은 강의를 통해 시큐리티를 배우고 있는 중입니다. 강의 중간중간에 동작 원리는 이전 강의 올려둔 거 참고하라고 말씀하셨는데 유튜브를 다 찾아보아도 없더라구요... 혹시 어디서 볼 수 있는지 알 수 있을까요?
-
미해결스프링 시큐리티
메인 페이지로 접속해도 login url로 리다이렉트가 되지 않습니다..
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/user").hasRole("USER") .anyRequest().permitAll(); http.formLogin(); } }@RestController public class SecurityController { @GetMapping("/") public String index() { return "home"; } @GetMapping("/user") public String user() { return "user"; } }
-
미해결스프링 시큐리티 완전 정복 [6.x 개정판]
세션클러스터링 적용후 중복로그인 체크
안녕하세요. 스프링 시큐리티 완전 정복 6.x 버전 잘 들었습니다.궁금한 점 이 있는데요.세션 클러스터링을 통해서 redis를 적용하면 세션이 tomcat -> rediss로 변경되는 부분 확인하였고, 잘 동작되는 것도 확인하였습니다.궁금한 점은 단일 서버일 때 중복 로그인 설정을 하면 session 체크를 ConcurrentSessionFilter에서 하는 것으로 알고 있는데, 세션 클러스터링을 적용하면 동시 세션을 어떻게 체크하는지 궁금하고, 이것을 제어하기 위해 설정이 추가로 필요한지 궁금합니다.단일 서버일 경우 sessionManagement를 통해서 maximumSessions(1) 인 것을 체크를 하게 되는데, 세션 클러스터링을 적용할 경우 이 값을 어떻게 공유하면서 처리하는지 궁금합니다.감사합니다.