묻고 답해요
167만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
안녕하세요 쿠키 관련 질문이 있습니다
안녕하세요 강의 정말 잘보고있습니다!!쿠키의 수명이 30일인데 만약 토큰의 세션값(UUID)이 탈취된다면 해당방식에선 어떻게 대응할수있을까요?httpOnly나 Secure옵션 등으로인해 현실적으로 탈취는 쉽지않을것이다.. 로만 생각하기엔 뭔가 찝찝한부분이 있는것같은데 제가 놓치고있는부분이 있을까요??또한 호돌님이 생각하시는 해당강의에서 다뤘던 쿠키에 세션토큰을 담아서 인증하는 방식의 단점이 궁금합니다!!
-
미해결스프링 시큐리티
formLogin - deprecated..
그래서 해당 강의에서 config 메서드를 제가 구글링 해보면서 해봤는데 인증을 아에 거치질 않네요.. 아래 메서드 한 번 확인해주시고 틀린 부분 있으면 말씀 부탁드립니다..추가로 앞으로 계속 코드가 달라질 거 같은데 이런 부분은 어떻게 해결해야 하는지.. 계속 구글링 해가면서 해야하는건가요..? @Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeRequests(authorizeRequests ->authorizeRequests.anyRequest().authenticated()).httpBasic(withDefaults()).formLogin(formLogin ->formLogin.loginPage("/loginPage").defaultSuccessUrl("/").usernameParameter("userId").passwordParameter("passwd").loginProcessingUrl("/login_proc").successHandler(new AuthenticationSuccessHandler() {@Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {System.out.println("authentication : "+ authentication.getName());response.sendRedirect("/");}}).failureHandler(new AuthenticationFailureHandler() {@Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {System.out.println("exception : "+ exception.getMessage());response.sendRedirect("/login");}}).permitAll());return http.build();}
-
미해결스프링 프레임워크는 내 손에 [스프1탄]
hikari config 에러
현재 hikariconfig 에러가 나고 있습니다. 어떤 해결책이 있을까요? 현재 roo-context.xml 과 pom.xml 은 작성한 것을 지우고 깃헙에서 코드를 그대로 복사해왔습니다. - Class 'com.zaxxer.hikari.HikariConfig' not found [config set: SpringMVC01/web-context]- Class 'com.zaxxer.hikari.HikariConfig' not found
-
미해결스프링부트 시큐리티 & JWT 강의
404에러 원인은???
강의 잘 들었습니다. 감사합니다.(_ _)완강을 하고 마지막으로 postman으로 http://localhost:8080/api/v1/user/asdf로 send해서 실험을 하고 있었는데(login은 ROLE_USER 권한만 가진 아이디로 로그인 했음) 404가 에러가 뜹니다. (manager, admin은 권한이 없기에 당연하게 403에러가 뜸) 404에러가 뜨는 이유가 권한이 있지만 redirect할 곳이 없어서 404에러가 발생하는 것인가요?
-
미해결스프링부트 시큐리티 & JWT 강의
로그인 올바르게 해도 login?error로 갑니다
SecurityConfig.java@Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig extends WebSecurityConfigurerAdapter { private final SecurityDetailsService securityDetailsService; @Override protected void configure(HttpSecurity http) throws Exception { http // .csrf().disable() .authorizeRequests() .antMatchers("/user/**").authenticated() .antMatchers("/admin/**").access("hasRole('ADMIN')") .anyRequest().permitAll() .and() .formLogin() .loginPage("/login") .loginProcessingUrl("/login") .defaultSuccessUrl("/home") .usernameParameter("userEmail") .and() .logout() .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/login") ; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } SecurityDetails.java@RequiredArgsConstructor public class SecurityDetails implements UserDetails { private final UserEntity userEntity; @Override public Collection<? extends GrantedAuthority> getAuthorities() { Collection<GrantedAuthority> authorities = new ArrayList<>(); authorities.add(new GrantedAuthority() { @Override public String getAuthority() { return userEntity.getAuthority().toString(); } }); return authorities; } @Override public String getPassword() { return userEntity.getUserPassword(); } @Override public String getUsername() { return userEntity.getUserEmail(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } } SecurityDetailsService.java@Service @RequiredArgsConstructor public class SecurityDetailsService implements UserDetailsService { private final UserRepository userRepository; @Override public UserDetails loadUserByUsername(String userEmail) throws UsernameNotFoundException { UserEntity userEntity = userRepository.findByUserEmail(userEmail); if(userEntity != null) return new SecurityDetails(userEntity); return null; } } SecurityDetails에서 return값이 boolean인 override 받는 메소드들 다 true로 해줬고login페이지나 home페이지에는 이미지도 없어서 문제될 게 없다고 생각되는데도통 이유를 모르겠습니다ㅠㅠㅠ
-
미해결스프링 프레임워크는 내 손에 [스프1탄]
커리큘럼 질문
커리큘럼 소개하실 때 스프 2탄 mvc07부분에서리액트와의 연동 방법을 간략하게나마 보여주신다고 하셨는데스프2탄 커리큘럼에는 없는 것 같아서요! 스프2탄 mvc07 강의듣다보면 내용이 나오나요??
-
미해결스프링부트 시큐리티 & JWT 강의
[급함]로그인시 jwt 발급 문제
https://github.com/YuYoHan/project_study1 전체 코드 질문 1) // 로그인 @PostMapping("/api/v1/users/login") public ResponseEntity<?> login(@RequestBody MemberDTO memberDTO) throws Exception { log.info("member : " + memberDTO); try { log.info("-----------------"); ResponseEntity<TokenDTO> login = memberService.login(memberDTO.getUserEmail(), memberDTO.getUserPw()); log.info("login : " + login); return ResponseEntity.ok().body(login); } catch (Exception e) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("문제가 있습니다"); } } // 로그인 public ResponseEntity<TokenDTO> login(String userEmail, String userPw) throws Exception { // Login ID/PW를 기반으로 UsernamePasswordAuthenticationToken 생성 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userEmail, userPw); log.info("----------------------"); log.info("authenticationToken : " +authenticationToken); log.info("----------------------"); // 실제 검증(사용자 비밀번호 체크)이 이루어지는 부분 // authenticateToken을 이용해서 Authentication 객체를 생성하고 // authentication 메서드가 실행될 때 // CustomUserDetailsService에서 만든 loadUserbyUsername 메서드가 실행 Authentication authentication = authenticationManagerBuilder .getObject().authenticate(authenticationToken); log.info("----------------------"); log.info("authentication : " + authentication); log.info("----------------------"); // 해당 객체를 SecurityContextHolder에 저장 SecurityContextHolder.getContext().setAuthentication(authentication); // authentication 객체를 createToken 메소드를 통해서 생성 // 인증 정보를 기반으로 생성 TokenDTO tokenDTO = jwtProvider.createToken(authentication); log.info("----------------------"); log.info("tokenDTO : " + tokenDTO); log.info("----------------------"); HttpHeaders headers = new HttpHeaders(); // response header에 jwt token을 넣어줌 headers.add(JwtAuthenticationFilter.HEADER_AUTHORIZATION, "Bearer " + tokenDTO); log.info("----------------------"); log.info("headers : " + headers); log.info("----------------------"); MemberEntity member = memberRepository.findByUserEmail(userEmail); log.info("member : " + member); TokenEntity tokenEntity = TokenEntity.builder() .grantType(tokenDTO.getGrantType()) .accessToken(tokenDTO.getAccessToken()) .refreshToken(tokenDTO.getRefreshToken()) .userEmail(tokenDTO.getUserEmail()) .nickName(member.getNickName()) .userId(member.getUserId()) .build(); log.info("token : " + tokenEntity); tokenRepository.save(tokenEntity); return new ResponseEntity<>(tokenDTO, headers, HttpStatus.OK); }package com.example.project1.config.auth; import com.example.project1.entity.member.MemberEntity; import lombok.Getter; import lombok.Setter; import lombok.ToString; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import java.util.ArrayList; import java.util.Collection; import java.util.Map; @Setter @Getter @ToString public class PrincipalDetails implements UserDetails, OAuth2User { private MemberEntity member; private Map<String, Object> attributes; // 일반 로그인 public PrincipalDetails(MemberEntity member) { this.member = member; } // OAuth2 로그인 public PrincipalDetails(MemberEntity member, Map<String, Object> attributes) { this.member = member; this.attributes = attributes; } // 해당 유저의 권한을 리턴하는 곳 @Override public Collection<? extends GrantedAuthority> getAuthorities() { Collection<GrantedAuthority> collection = new ArrayList<>(); collection.add(new GrantedAuthority() { @Override public String getAuthority() { return "ROLE_" + member.getUserType().toString(); } }); return collection; } // 사용자 패스워드를 반환 @Override public String getPassword() { return member.getUserPw(); } // 사용자 이름 반환 @Override public String getUsername() { return member.getUserEmail(); } // 계정 만료 여부 반환 @Override public boolean isAccountNonExpired() { // 만료되었는지 확인하는 로직 // true = 만료되지 않음 return true; } // 계정 잠금 여부 반환 @Override public boolean isAccountNonLocked() { // true = 잠금되지 않음 return true; } // 패스워드의 만료 여부 반환 @Override public boolean isCredentialsNonExpired() { // 패스워드가 만료되었는지 확인하는 로직 // true = 만료되지 않음 return true; } // 계정 사용 가능 여부 반환 @Override public boolean isEnabled() { // 계정이 사용 가능한지 확인하는 로직 // true = 사용 가능 return true; } @Override public Map<String, Object> getAttributes() { return attributes; } @Override public String getName() { return null; } }@Service @RequiredArgsConstructor @Slf4j public class PrincipalDetailsService implements UserDetailsService { private MemberRepository memberRepository; // 시큐리티 session = Authentication = UserDetails // 함수 종료시 @AuthenticationPrincipal 어노테이션이 만들어진다. @Override public UserDetails loadUserByUsername(String userEmail) throws UsernameNotFoundException { MemberEntity member = memberRepository.findByUserEmail(userEmail); log.info("user : " + member); return new PrincipalDetails(member); } }package com.example.project1.config.jwt; import com.example.project1.domain.jwt.TokenDTO; import io.jsonwebtoken.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; 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.userdetails.User; import org.springframework.stereotype.Component; import io.jsonwebtoken.security.Keys; import javax.xml.bind.DatatypeConverter; import java.security.Key; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.stream.Collectors; @Slf4j @Component public class JwtProvider { private static final String AUTHORITIES_KEY = "auth"; @Value("${jwt.access.expiration}") private long accessTokenTime; @Value("${jwt.refresh.expiration}") private long refreshTokenTime; private Key key; public JwtProvider( @Value("${jwt.secret_key}") String secret_key) { byte[] secretByteKey = DatatypeConverter.parseBase64Binary(secret_key); this.key = Keys.hmacShaKeyFor(secretByteKey); } // 유저 정보를 가지고 AccessToken, RefreshToken 을 생성하는 메소드 public TokenDTO createToken(Authentication authentication) { // 권한 가져오기 String authorities = authentication.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.joining(",")); long now = (new Date()).getTime(); Date now2 = new Date(); // AccessToken 생성 Date accessTokenExpire = new Date(now + this.accessTokenTime); String accessToken = Jwts.builder() // 내용 sub : 유저의 이메일 // 토큰 제목 .setSubject(authentication.getName()) // 클레임 id : 유저 ID .claim(AUTHORITIES_KEY, authorities) // 내용 exp : 토큰 만료 시간, 시간은 NumericDate 형식(예: 1480849143370)으로 하며 // 항상 현재 시간 이후로 설정합니다. .setExpiration(accessTokenExpire) // 서명 : 비밀값과 함께 해시값을 ES256 방식으로 암호화 .signWith(key, SignatureAlgorithm.HS256) .compact(); log.info("accessToken : " + accessToken); // RefreshToken 생성 Date refreshTokenExpire = new Date(now + this.refreshTokenTime); String refreshToken = Jwts.builder() .setSubject(authentication.getName()) .claim(AUTHORITIES_KEY, authorities) .setExpiration(refreshTokenExpire) .signWith(key, SignatureAlgorithm.HS256) .compact(); log.info("refreshToken : " + refreshToken); return TokenDTO.builder() .grantType("Bearer") .accessToken(accessToken) .refreshToken(refreshToken) // principalDeatails에서 getUserName 메소드가 반환한 것을 담아준다. // 이메일을 반환하도록 구성했으니 이메일이 반환됩니다. .userEmail(authentication.getName()) .build(); } // accessToken 생성 public TokenDTO createAccessToken(String userEmail) { Long now = (new Date()).getTime(); Date now2 = new Date(); Date accessTokenExpire = new Date(now + this.accessTokenTime); String accessToken = Jwts.builder() .setIssuedAt(now2) .setSubject(userEmail) .setExpiration(accessTokenExpire) .signWith(key, SignatureAlgorithm.HS256) .compact(); log.info("accessToken : " + accessToken); return TokenDTO.builder() .grantType("Bearer ") .accessToken(accessToken) .userEmail(userEmail) .build(); } // JWT 토큰을 복호화하여 토큰에 들어있는 정보를 꺼내는 코드 // 토큰으로 클레임을 만들고 이를 이용해 유저 객체를 만들어서 최종적으로 authentication 객체를 리턴 // 인증 정보 조회 public Authentication getAuthentication(String token) { // 토큰 복호화 메소드 Claims claims = parseClaims(token); if(claims.get("auth") == null) { throw new RuntimeException("권한 정보가 없는 토큰입니다."); } // 클레임 권한 정보 가져오기 Collection<? extends GrantedAuthority> authorities = Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); // UserDetails 객체를 만들어서 Authentication 리턴 User principal = new User(claims.getSubject(), "", authorities); return new UsernamePasswordAuthenticationToken(principal, token, authorities); } private Claims parseClaims(String token) { try { return Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody(); } catch (ExpiredJwtException e) { log.info("ExpiredJwtException : " + e.getMessage()); log.info("ExpiredJwtException : " + e.getClaims()); return e.getClaims(); } } // 토큰의 유효성 검증을 수행 public boolean validateToken(String token) { try { Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token); return true; } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { log.info("잘못된 JWT 서명입니다."); } catch (ExpiredJwtException e) { log.info("만료된 JWT 토큰입니다."); } catch (UnsupportedJwtException e) { log.info("지원되지 않는 JWT 토큰입니다."); }catch (IllegalArgumentException e) { log.info("JWT 토큰이 잘못되었습니다."); } return false; } }@RequiredArgsConstructor @Slf4j public class JwtAuthenticationFilter extends GenericFilterBean { public static final String HEADER_AUTHORIZATION = "Authorization"; private final JwtProvider jwtProvider; // doFilter는 토큰의 인증정보를 SecurityContext에 저장하는 역할 수행 @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) request; // Request Header에서 JWT 토큰을 추출 String jwt = resolveToken(httpServletRequest); String requestURI = httpServletRequest.getRequestURI(); if(StringUtils.hasText(jwt) && jwtProvider.validateToken(jwt)){ // 토큰이 유효할 경우 토큰에서 Authentication 객체를 가지고 와서 SecurityContext에 저장 Authentication authentication = jwtProvider.getAuthentication(jwt); SecurityContextHolder.getContext().setAuthentication(authentication); log.info("Security Context에 '{}' 인증 정보를 저장했습니다., uri : {}", authentication.getName(), requestURI); } else { log.debug("유효한 JWT 토큰이 없습니다. uri : {}", requestURI); } chain.doFilter(request, response); } // Request Header 에서 토큰 정보를 꺼내오기 위한 메소드 private String resolveToken(HttpServletRequest httpServletRequest) { String bearerToken = httpServletRequest.getHeader(HEADER_AUTHORIZATION); if(StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } else { return null; } } }대략 적인 코드는 다음과 같습니다.근데 컨트롤러에서 로그인 시 Exception에 걸려서 문제가 있다고 문구 찍은게 나오네요. log 돌려보니까 service에서 authenticationToken객체는 나오는데 authentication 여기서 부터 안나오는거 보니 여기서 문제가 있는거 같은데 400번 bad Request가 뜹니다 ㅠㅠ 질문2) 현재 방법이 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userEmail, userPw);을 통해서 authentication으로 token을 생성하고 있는데 그냥 userEmail로만 받고 // accessToken 생성 public TokenDTO createAccessToken(String userEmail) { Long now = (new Date()).getTime(); Date now2 = new Date(); Date accessTokenExpire = new Date(now + this.accessTokenTime); String accessToken = Jwts.builder() .setIssuedAt(now2) .setSubject(userEmail) .setExpiration(accessTokenExpire) .signWith(key, SignatureAlgorithm.HS256) .compact(); log.info("accessToken : " + accessToken); return TokenDTO.builder() .grantType("Bearer ") .accessToken(accessToken) .userEmail(userEmail) .build(); }이런식으로 토큰을 생성해도 괜찮나요?질문3) JwtAuthenticationFilter 클래스에서 @RequiredArgsConstructor @Slf4j public class JwtAuthenticationFilter extends GenericFilterBean { public static final String HEADER_AUTHORIZATION = "Authorization"; private final JwtProvider jwtProvider; // doFilter는 토큰의 인증정보를 SecurityContext에 저장하는 역할 수행 @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) request; // Request Header에서 JWT 토큰을 추출 String jwt = resolveToken(httpServletRequest); String requestURI = httpServletRequest.getRequestURI(); if(StringUtils.hasText(jwt) && jwtProvider.validateToken(jwt)){ // 토큰이 유효할 경우 토큰에서 Authentication 객체를 가지고 와서 SecurityContext에 저장 Authentication authentication = jwtProvider.getAuthentication(jwt); SecurityContextHolder.getContext().setAuthentication(authentication); log.info("Security Context에 '{}' 인증 정보를 저장했습니다., uri : {}", authentication.getName(), requestURI); } else { log.debug("유효한 JWT 토큰이 없습니다. uri : {}", requestURI); } chain.doFilter(request, response); } // Request Header 에서 토큰 정보를 꺼내오기 위한 메소드 private String resolveToken(HttpServletRequest httpServletRequest) { String bearerToken = httpServletRequest.getHeader(HEADER_AUTHORIZATION); if(StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } else { return null; } } }이 처리를 해줬으니 만약 access token이 만료되서 refresh token을 보내서 access token을 발급받으려고 할 때 Bearer가 있는지 확인을 더 해줄 필요 없이 여기서 처리하니 바로 header에 담겨온 refresh token을 빼와서 유효성 검사를 해주고 access token을 발급해주면 되나요?
-
해결됨스프링부트 시큐리티 & JWT 강의
페이스북 로그인이 안 됩니다.
시큐리티 10강 페이스북 로그인을 하려고 하면WARN 24016 --- [nio-8080-exec-2] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [231] milliseconds.이런 에러가 발생합니다. 이 에러가 발생하기 전에 2. JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 이 에러가 먼저 발생해서 application.yml에 jpa: open-in-view: false이 코드를 추가해서 고쳤습니다. 2번을 고치고 나서 다시 실행해보니 1번 에러가 발생했는데 어떻게 고쳐야할지 모르겠습니다.
-
미해결호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
세션과 토큰을 이용한 로그인 유지 방식의 차이점
안녕하세요! 강의를 보다가 의문점이 생겨 질문드립니다.크게 아래와 같이 두 가지 질문이 생겼습니다.로그인 유지를 위해 remember-me 토큰을 발급하고 해당 토큰의 유효기간을 (예를 들어) 30일로 설정하여 유저의 세션이 만료되어도 로그인이 풀리지 않게 한다면 단순히 최초에 저장되는 세션의 유효기간을 30일로 늘리는 것과 비교해 보안 측면에서 어떠한 장점을 갖는지 의문이 들었습니다.결론적으로 만약 리프레시 토큰을 사용한다고 하면 리프레시 토큰이 만료되기 전에 이를 갱신할 책임은 클라이언트에게 있는 건가요?? DB를 사용하지 않는 remember-me 방식이라고하면 토큰에서만 expired 관련 정보를 알 수 있을 것이고 그렇다면 클라이언트에서 이를 디코딩하여 남은 유효기간을 확인 후 직접 다시 요청을 하는 식의 처리를 해서 Cookie를 갈아주어야 하는 것인가하는 생각이 들었습니다.먼저 2번의 경우 강의에서의 세션=액세스 토큰, remember-me 토큰=리프레시 토큰이라고 비슷하게 생각할 수 있을 것 같아서 카카오 api 문서를 참고해봤는데,카카오에서는 리프레시 토큰의 유효기간이 1달 이내일 경우 액새스 토큰 갱신 요청을 보낼 때 리프레시 토큰도 같이 갱신하여 보내준다고 하더라구요. (https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#refresh-token)2번의 경우 이렇게 이해하면 되는건지와, 1번에 대해서는 어떻게 생각하시는지 궁금합니다!
-
미해결스프링부트 시큐리티 & JWT 강의
findByUsername(username)을 사용하는 이유가 궁금합니다.
안녕하세요 강사님 궁금한 점이 해결되지 않아서 질문 남깁니다.강사님 git에 있는 소스를 그대로 갖고 왔습니다.토큰이 정상적인 상황일 때, 즉 username 값이 존재할 때 findByUsername을 사용해서 user객체를 얻는 장면인데 토큰 안에 User객체 자체를 저장해서 불필요한 DB연동을 안 하는 방식은 잘못된 방식인가요?제 생각에는 이렇게 사용하면 토큰에 User 정보가 노출되기 때문에 보안이 취약하다 라고 생각하는데 이 생각이 맞는지 궁금합니다.username은 충분히 겹칠 수 있는 값이라고 생각이 드는데 토큰을 저장할 때 Id값을 저장해서 꺼내오는 방식은 잘못된 방식일까요?
-
미해결스프링부트 시큐리티 & JWT 강의
key 보관 방법
수업 듣다가 궁금증이 생겨서 남깁니다.key 생성 시에 현재 실습에서는 "cos" 를 사용했는데, 실제로 사용할때는 key를 어떻게 생성하고, 보관해야하는지 궁금합니다.
-
해결됨스프링 시큐리티
요청을 확인할 수 있는 방법이 있을까요??
안녕하세요 선생님 좋은강의 정말 감사드립니다!선생님 혹시 사용자의 어떤 request에 의해서 CustomAccessDeniedHandler 여기로 오게 되는지 디버그를 이용해서 확인하고 싶다면 어떤 필터를 확인하면 알 수 있을까요??
-
미해결스프링 시큐리티
AuthenticationProvider 등록 관해서 질문이 있습니다.
안녕하세요 선생님.스프링 부트 2.7.x 버전에서 하기 스크린샷과 같이 설정 하였을때 인증프로바이더가 중복으로 등록 되는 문제가 발생하였습니다. 하기와 같이 인증매니저를 설정을 수정하니인증프로바이더가 정상적으로 1개 등록되었습니다.왜 이런 일이 발생하는지 잘 이해가 되지 않아서요..선생님께서 이유를 아신다면 설명해주시면 감사하겠습니다.
-
미해결스프링 시큐리티
스프링부트 dependencies 필요하신분
//타임리프 implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' // 스프링 시큐리티 implementation 'org.springframework.boot:spring-boot-starter-security' //jpa implementation 'org.springframework.boot:spring-boot-starter-data-jpa' //web implementation 'org.springframework.boot:spring-boot-starter-web' //postgresql 드라이버 runtimeOnly 'org.postgresql:postgresql' //모델 mapper implementation 'org.modelmapper:modelmapper:3.1.1' // lombok compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' // devtools developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test'
-
미해결스프링 프레임워크는 내 손에 [스프1탄]
컴파일 오류
csrf 강의 들으면서 실행중에 No bean named 'springSecurityFilterChain' available이라고 에러가 떳습니다. 어떻게 해결해야하나요
-
미해결스프링부트 시큐리티 & JWT 강의
UserDetails 안에 dto
안녕하세요. 좋은 강의 만들어주셔서 감사합니다. 궁금한 점이 생겨서 질문드립니다.강의에서는 UserDetails를 구현할 때 내부에 엔티티 자체를 넣어주셨는데 엔티티 자체를 넣는게 엔티티를 dto로 변환 후 넣는 것보다 좋나요?
-
미해결스프링 시큐리티
authenticationEntryPoint 에서 sendRedirect말고 formLogin을 다시 띄워주는 방법
제목과 일치합니다.response.sendredirect하지않고 security에서 제공하는 formLogin을 띄워주려면 어떻게 코드를 작성 해야 하나요?
-
미해결스프링 프레임워크는 내 손에 [스프2탄]
강사님 질문입니다!
저는 페이징과 검색위주로 보고자 이 강의를 구매하게되었습니다. 프로젝트 진행중이라서 게시판이나 답글은 많이 해봤어서 페이징으로 넘어가고싶은데.. 이럴려면 페이징 이전의소스가 필요해서요.. 프로젝트가 만히 급해서.. 혹시 회차별로 소스코드제공이 가능할까요? ㅠㅠ..
-
해결됨호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)
9:27 에 나오는 부분 찾아봤습니다.
public static MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables) { return MockMvcRequestBuilders.get(urlTemplate, urlVariables) .requestAttr(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, urlTemplate); }위의 코드는 RestDocumentationRequestBuilders의 get()입니다.Spring REST Docs2 - 요청, 응답필드의 9:27에서 하신 말씀 듣고 상속 관계이지 않을까하는 생각이 들었고 궁금해서 들어가보니 상속이 아닌RestDocumentationRequestBuilders의 get()에서 내부적으로 MockMvcRequestBuilders의 get()를 호출해주더라구요.MockMvcRequestBuilders가 추상클래스지만 get()이 static으로 선언되어 있어 상속을 해도 오버라이드를 할 수 없기에 저런 식으로 만들었지 않았을까?라고 추측을 해봤습니다.그러면서 추가적으로 위의 클래스들이 추상클래스로 만들어져 있고 메소드가 전부 static으로 선언되어 있는 것에 대해 이유가 궁금했습니다.추상클래스는 추상 메소드를 선언하고 상속을 하면서 오버라이드를 통한 다형성을 위해 사용한다고 알고 있었는데 여기서는 다른 목적과 방식으로 사용하고 있는 것처럼 보였기 때문입니다.그래서 검색을 해봤지만 키워드를 잘못 선택했는지명확하게 답을 찾지는 못했고, 추상 클래스와스태틱 메소드에 대해 각각 찾아보면서"객체 생성 제한과 메모리 이득 때문인가?"라는 생각이 들더라구요.하지만 추상클래스도 익명객체를 사용하면 객체 생성이 가능해지는 걸로 아는데 그래서인지RestDocumentationRequestBuilders는 생성자도 private으로 선언해 익명 객체로도 생성이 안되게 막아 놨지만 MockMvcRequestBuilders같은 경우는 생성자를 따로 막아 놓지 않아서 익명 객체로 생성이 가능하더라구요. 이렇게 차이를 두는 이유는 뭔가요??그리고 위의 클래스들처럼 선언한 이유도 궁금합니다.
-
미해결스프링 프레임워크는 내 손에 [스프1탄]
회원수정 프로파일 컨트롤러에서 수정하신부분
폼에서 히든으로 프로파일 넘겨버려도 될까요?저만 안되는줄 알고 그렇게 처리했더니 정상작동하길래 혹시나 나중에 안좋은 코드일까해서 여쭈어봅니다!