묻고 답해요
130만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결지금 당장 NodeJS 백엔드 개발 [사주 만세력]
settings.json 에서 3번 위치에 formatOnSave 를 true 로 변경하려는데 강의 화면과 다릅니다.
위 화면이 아니고 아래 화면이 나와서 True로 변경할 수가 없습니다. 도와주세요.
-
미해결지금 당장 NodeJS 백엔드 개발 [사주 만세력]
settings.json 에서 3번 위치에 formatOnSave 를 true 로 변경하는 화면이 왜 다를까요?
-
미해결스프링부트 시큐리티 & JWT 강의
회원정보를 조회하는 API서버가 따로 있을때 로직 분리
당연히 웹앱이 API에 요청을 할때도 올바른 대상이 요청하는게 맞는지 별도의 검증이 필요하지만우선 그건 무시하고 순수히 웹앱의 유저 인증만 생각했을때의 이야기입니다.. 프론트 역할을 하는html, css, (바닐라js or jQuery) + spring boot(thymeleaf, spring security) 웹어플리케이션 프로젝트가 있고회원이 있는지 조회할 수 있는 API 서버(DB와 연결된 spring boot)가 별도로 존재했을때 어떤 프로젝트에 어떤 식으로 시큐리티 및 토큰생성 세팅을 해야할지 감이 잘 오지 않습니다.. 제가 구현하고자 하는건 회원/비회원에 따라페이지를 동적으로 바꾸거나 (로그인이 로그아웃으로 바뀐다든지)페이지에 접근을 못하게 하려고 합니다 (마이페이지) 제 생각에는 구현내용 둘 다 API를 굳이 갈 필요가 없기 때문에 웹앱단에서 검증이 이루어져야 할 것 같은데 맞을까요..? API는 회원 유무를 조회한 뒤, 존재하는 경우 단순히 유저정보(or 아예 토큰을 만들어서 넘긴다..?)를 웹앱에 넘겨주는 것까지가 역할이고, 따라서 Spring Security는 여기서 필요하지 않다 웹앱 프로젝트에 스프링 시큐리티 설정을 한 뒤, 스프링부트단에서 API로부터 전달받은 토큰, 혹은 유저정보를 가지고 인증을 처리한다 (하지만 어떻게..?) 이런 흐름이 맞는지 모르겠습니다..
-
해결됨스프링부트 시큐리티 & JWT 강의
SecurityFilterChain에서 login 이후에 authenticated 인증 처리 오류?
안녕하세요 수업중 막히는 부분이 있어서 질문 남깁니다.현재 spring 3, security 6.2버전으로 진행중입니다.구글링해서 강의 버전에 따른 오류 부분은 고쳤는데요.. '문제는 로그인 처리해서 PrincipalDetails에 db에 있는 유저 값을 잘 담기는 했는데.. security config에서 설정한 권한별 경로로 접근하는순간 302로 다시 로그인 홈페이지로 리다이렉트 돼서 수업 진행이 안됩니다.. 뭐가 문제인걸까요? ㅜㅜ@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .cors(AbstractHttpConfigurer::disable) .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); http .authorizeHttpRequests(au -> au.requestMatchers("/", "/join", "/login").permitAll() .requestMatchers("/user/**").authenticated() .requestMatchers("/manager/**").hasAnyRole("ADMIN", "MANAGER") .requestMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() ); http.formLogin(f -> f.loginPage("/loginForm") .loginProcessingUrl("/login") .usernameParameter("userName") .passwordParameter("password") .defaultSuccessUrl("/") .permitAll()) .httpBasic(h -> h.disable()); // logout http.logout(logout -> logout. logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/loginForm")); return http.build(); }
-
미해결지금 당장 NodeJS 백엔드 개발 [사주 만세력]
docker containers failed connect
docker 설치를 했는데,containers를 보면 failed to connect라고 나옵니다.
-
미해결지금 당장 NodeJS 백엔드 개발 [사주 만세력]
MySQL Workbench 접속 연결 에러
아래 팝업 화면으로 계속 에러가 나고 있습니다.Failed to connect to MySQL at 127.0.0.1:3309 with user rootunable to connect to 127.0.0.1:3309
-
미해결스프링부트 시큐리티 & JWT 강의
JWTAuthorizationFilter에서,,
강의를 토대로 로그인 페이지를 구현하고, 이를 이용해서 로그인 과정을 거치는 로직을 구현하는 도중에 문제가 발생했습니다.커스텀 필터를 만들어서 각각 JWTAuthenticationFilter와 JWTAuthorizationFilter를 거치게끔 해놓고, JWTAuthenticationFilter까지는 잘 마무리 지었습니다만, successfulAuthentication 메소드에 response를 설정하고 JWTAuthorizationFilter로 넘길 때 request에 Token을 받아들이지 못합니다.(포스트맨으로 넘길 때는 잘 나오는데 왜그러는지 모르겠네요,,) @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { System.out.println("========================================="); System.out.println("Authentication이 실행됨 : 인증이 완료되었다는 뜻임"); PrincipalDetails principalDetails=(PrincipalDetails)authResult.getPrincipal(); //RSA방식이 아닌, Hash암호방식 String jwtToken = JWT.create() .withSubject(principalDetails.getUsername()) // token 별명 느낌? .withExpiresAt(new Date(System.currentTimeMillis()+JWTProperties.EXPIRATION_TIME)) // Token 만료 시간 -> 현재시간 + 만료시간 .withClaim("id", principalDetails.getMember().getMemberID()) // 비공개 Claim -> 넣고싶은거 아무거나 넣으면 됨 .withClaim("username", principalDetails.getMember().getMemberName()) // 비공개 Claim .sign(Algorithm.HMAC512(JWTProperties.SECRET)); // HMAC512는 SECRET KEY를 필요로 함 //String jwtToken =TokenUtils.generateJwtToken(principalDetails.getMember()); response.addHeader(JWTProperties.HEADER_STRING, JWTProperties.TOKEN_PREFIX+jwtToken); response.setHeader(JWTProperties.HEADER_STRING, JWTProperties.TOKEN_PREFIX+jwtToken); response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); System.out.println("response : "+response); System.out.println("JWTAuthenticationFilter에서의 response.getHeader('Authorization')) : "+response.getHeader(JWTProperties.HEADER_STRING)); [JWTAuthorizationFilter.java] @Log4j2 public class JWTAuthorizationFilter extends BasicAuthenticationFilter { private final MemberRepository memberRepository; public JWTAuthorizationFilter(AuthenticationManager authenticationManager, MemberRepository memberRepository){ super(authenticationManager); System.out.println("JWTAuthorizationFilter : 인증이나 권한이 필요한 주소가 요청됨"); System.out.println("========================================="); this.memberRepository=memberRepository; } // 인증이나 권한이 필요한 주소 요청이 있을 때 해당 필터를 타게 됨 @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { //String header=request.getHeader("Authorization"); System.out.println("request : "+request); System.out.println("Authorization : "+request.getHeader(JWTProperties.HEADER_STRING)); String header=request.getHeader(JWTProperties.HEADER_STRING); System.out.println("JWTAuthorizationFilter에서의 JWTHeader : "+header); // JWT Token // Enumeration<String> headerNames = request.getHeaderNames(); // while (headerNames.hasMoreElements()) { // String headerName = headerNames.nextElement(); // System.out.println("Header: " + headerName + ", Value: " + request.getHeader(headerName)); // } // header가 있는지(유효한지) 확인 // 토큰이 잘못될 경우 다음 filter로 흘려 보낸다. if(header==null||!header.startsWith(JWTProperties.TOKEN_PREFIX)){ System.out.println("Not Allowed User"); chain.doFilter(request,response); return; } // JWT Token을 검증해서 정상적인 사용자인지 확인 String token = request.getHeader(JWTProperties.HEADER_STRING).replace(JWTProperties.TOKEN_PREFIX, ""); String memberID = JWT.require(Algorithm.HMAC512(JWTProperties.SECRET)).build().verify(token).getClaim("memberID").asString(); // verify()를 통해서 서명 System.out.println("token : "+token); System.out.println("memberID : "+memberID); // 서명이 정상적으로 동작했을 경우 if(memberID!=null){ Member memberEntity = memberRepository.findByMemberID(memberID); System.out.println("UserEntity 정상 : " +memberEntity); PrincipalDetails principalDetails = new PrincipalDetails(memberEntity); System.out.println("MemberName : "+memberEntity.getMemberName()); // JWT Token 서명을 통해서 서명이 정상적이면 Authentication 객체를 만들어준다. Authentication authentication = new UsernamePasswordAuthenticationToken(principalDetails, null, principalDetails.getAuthorities()); System.out.println("JWTAuthorization에서의 authentication : "+authentication); // 강제로 Security의 Session에 접근하여서 Authentication 객체를 저장시킨다. SecurityContextHolder.getContext().setAuthentication(authentication); System.out.println("Successfully Saved Authentication" + authentication); } // super.doFilterInternal(request, response, chain); chain.doFilter(request,response); } } 더 자세한 내용은 github 참고 부탁드립니다.https://github.com/msun0215/SWProject/tree/1208
-
해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
async function을 생략하고 바로 await 하는 부분이 잘 이해가 안됩니다
async function ( if (){await 어쩌구} ) 여기서 if문 안에 await가 들어있으면 await가 있는 곳이 최상위 스코프가 아닌데 작동이 가능한가요? 최상위 스코프에서만 async function 생략 가능하다는 말은 async function(await 어쩌구) 이래야 바로 await 어쩌구 로 꺼낼 수 있고 if(){await 어쩌구} 는 async function 밖으로 꺼낼 수 없는 것으로 이해되어서요..제가 최상위 스코프가 뭔지 잘 모르는 것 같기도 합니다..ㅠㅠ[제로초 강좌 질문 필독 사항입니다]질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다.도움이 되는 질문을 하는 방법을 알려드립니다.https://www.youtube.com/watch?v=PUKOWrOuC0c0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다.1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다.2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다.3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요.4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요.5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다.6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다.
-
미해결따라하며 배우는 NestJS
port 5432 failed: recived invalid response to ssl negotiation
이런 오류메세지가 나오는데 방법좀 부탁드립니다. nestJS서버는 5432포트로 돌아가고 있습니다!!
-
해결됨[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
passport 미들웨어를 express-session 밑에다가 반드시 적어야하는 이유
[passport 세팅 및 회원가입 만들기] 강의 중 passport 미들웨어를 왜 express-session 밑에다가 반드시 적어야한다고 하셨는데 이유는 나오지 않았었습니다이유는 무엇일까요?GPT도 써보았지만 생성형 AI라서 틀린 대답일 수 있으므로 강의자분께 질문드립니다.
-
미해결Spring Boot JWT Tutorial
Spring boot 3.1.5 기준 학습 정리 파일 공유
2023년 11월 말 JWT학습 본 무료강의를 알게돼 학습했습니다. 학습중에 일부 메서드나 이나 라이브러리들이 deprecate 인 경우가 있어서 학습 중 정리한 markdown 파일 공유합니다 ㅎㅎ 소스도 같이 공유되어 있으니 학습시 참고하시면 좋을 것 같네요! https://github.com/gomshiki/jwtStudy/blob/main/studymarkdown/jwtProject_note.md
-
미해결스프링부트 시큐리티 & JWT 강의
혹시 마지막 강의 27강 11분쯤 Header에 토큰값 못가져오는경우
안녕하세요. 혹시 PostMan으로 Authorization 체크 해제 후 Post했을때 500error 뜰경우 ( MyFilter3 에 nullpoint오류 )Spring Security 설정에서 MyFilter3() 필터설정부분 주석해주시면 정상적으로 진행됩니다~!
-
미해결Spring Boot JWT Tutorial
/api/hello에 접근이 안됩니다 ㅠㅠ
package NewYear.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; 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.WebSecurityCustomizer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; //기본적인 웹 보안을 활성화 하는 어노테이션 @Configuration @EnableWebSecurity @EnableMethodSecurity public class SecurityConfig { @Bean public WebSecurityCustomizer configure() { return (web) -> web.ignoring() .requestMatchers(new AntPathRequestMatcher("/h2-console/**")) .requestMatchers(new AntPathRequestMatcher("/favicon.ico")); } @Bean public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { return httpSecurity .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests((registry) -> registry.requestMatchers(new AntPathRequestMatcher("/api/hello")).permitAll() .anyRequest().authenticated() ) .build(); } } @EnableWebSecurity를 비활성화도 해보고 커뮤니티에 올라온 코드로 다 해봤는 데 접근이 401에러로 접근이 안되는 것 같습니다 ㅠㅠ 해결방안이 있을까요 스프링부트 버전은 3.2.0입니다
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
9장 게시글 업로드하기 post 오류
[제로초 강좌 질문 필독 사항입니다]질문에는 여러분에게 도움이 되는 질문과 도움이 되지 않는 질문이 있습니다.도움이 되는 질문을 하는 방법을 알려드립니다.https://www.youtube.com/watch?v=PUKOWrOuC0c0. 숫자 0부터 시작한 이유는 1보다 더 중요한 것이기 때문입니다. 에러가 났을 때 해결을 하는 게 중요한 게 아닙니다. 왜 여러분은 해결을 못 하고 저는 해결을 하는지, 어디서 힌트를 얻은 것이고 어떻게 해결한 건지 그걸 알아가셔야 합니다. 그렇지 못한 질문은 무의미한 질문입니다.1. 에러 메시지를 올리기 전에 반드시 스스로 번역을 해야 합니다. 번역기 요즘 잘 되어 있습니다. 에러 메시지가 에러 해결 단서의 90%를 차지합니다. 한글로 번역만 해도 대부분 풀립니다. 그냥 에러메시지를 올리고(심지어 안 올리는 분도 있습니다. 저는 독심술사가 아닙니다) 해결해달라고 하시면 아무런 도움이 안 됩니다.2. 에러 메시지를 잘라서 올리지 않아야 합니다. 입문자일수록 에러메시지에서 어떤 부분이 가장 중요한 부분인지 모르실 겁니다. 그러니 통째로 올리셔야 합니다.3. 코드도 같이 올려주세요. 다만 코드 전체를 다 올리거나, 깃헙 주소만 띡 던지지는 마세요. 여러분이 "가장" 의심스럽다고 생각하는 코드를 올려주세요.4. 이 강좌를 바탕으로 여러분이 응용을 해보다가 막히는 부분, 여러 개의 선택지 중에서 조언이 필요한 부분, 제 경험이 궁금한 부분에 대한 질문은 대환영입니다. 다만 여러분의 회사 일은 질문하지 마세요.5. 강좌 하나 끝날 때마다 남의 질문들을 읽어보세요. 여러분이 곧 만나게 될 에러들입니다.6. 위에 적은 내용을 명심하지 않으시면 백날 강좌를 봐도(제 강좌가 아니더라도) 실력이 늘지 않고 그냥 코딩쇼 관람 및 한컴타자연습을 한 셈이 될 겁니다. 사진업로드를 하려할때 미리보기가 뜨지 않습니다. uploads에는 올린 사진들이 잘 뜹니다.게시글을 업로드하려 짹짹을 누르면 post 라우터가 없다고 뜹니다. POST /post 라우터가 없습니다.404Error: POST /post 라우터가 없습니다. at C:\Users\jyoun\udr_node\lecture\ch9\app.js:53:18 at Layer.handle [as handle_request] (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\layer.js:95:5) at trim_prefix (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:328:13) at C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:286:9 at Function.process_params (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:346:12) at next (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:280:10) at C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:646:15 at next (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\index.js:265:14) at C:\Users\jyoun\udr_node\lecture\ch9\routes\page.js:12:3 at Layer.handle [as handle_request] (C:\Users\jyoun\udr_node\lecture\ch9\node_modules\express\lib\router\layer.js:95:5) controllers/post.jsconst Post = require('../models/post'); const Hashtag = require('../models/hashtag'); exports.afterUploadImage = (req, res) => { console.log(req.file); res.json({ url: `/img/${req.file.filename}` }); }; exports.uploadPost = async (req, res, next) => { try { const post = await Post.create({ content: req.body.content, img: req.body.url, UserId: req.user.id, }); const hashtags = req.body.content.match(/#[^\s#]*/g); if (hashtags) { const result = await Promise.all(hashtags.map((tag) => { return Hashtag.findOrCreate({ where: { title: tag.slice(1).toLowerCase() } }); })); console.log('result', result); await post.addHashtags(result.map(r => r[0])); } res.redirect('/'); } catch (error) { console.error(error); next(error); } }; routes/post.jsconst express = require('express'); const multer = require('multer'); const path = require('path'); const fs = require('fs'); const { afterUploadImage, uploadPost } = require('../controllers/post'); const { isLoggedIn } = require('../middlewares'); const router = express.Router(); try { fs.readdirSync('uploads'); } catch (error) { console.error('uploads 폴더가 없어 uploads 폴더를 생성합니다.'); fs.mkdirSync('uploads'); } const upload = multer({ storage: multer.diskStorage({ destination(req, file, cb) { cb(null, '/uploads'); }, filename(req, file, cb) { const ext = path.extname(file.originalname); cb(null, path.basename(file.originalname, ext) + Date.now() + ext); }, }), limits: { fileSize: 5 * 1024 * 1024 }, }); // POST /post/img router.post('/img', isLoggedIn, upload.single('img'), afterUploadImage); // POST /post const upload2 = multer(); router.post('/', isLoggedIn, upload2.none(), uploadPost); module.exports = router; 개발자 도구로 보면 짹짹을 눌렀을때 갈곳이 없다는데 저는 깃헙 복사해서 똑같이 했는데 뭐가 문제인지 모르겠습니다. app.jsconst express = require('express'); const cookieParser = require('cookie-parser'); const morgan = require('morgan'); const path = require('path'); const session = require('express-session'); const nunjucks = require('nunjucks'); const dotenv = require('dotenv'); const passport = require('passport'); dotenv.config(); const pageRouter = require('./routes/page'); const authRouter = require('./routes/auth'); const { sequelize } = require('./models'); const passportConfig = require('./passport'); const app = express(); passportConfig(); // 패스포트 설정 app.set('port', process.env.PORT || 8001); app.set('view engine', 'html'); nunjucks.configure('views', { express: app, watch: true, }); sequelize.sync({ force: false }) .then(() => { console.log('데이터베이스 연결 성공'); }) .catch((err) => { console.error(err); }); app.use(morgan('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser(process.env.COOKIE_SECRET)); app.use(session({ resave: false, saveUninitialized: false, secret: process.env.COOKIE_SECRET, cookie: { httpOnly: true, secure: false, }, })); app.use(passport.initialize()); app.use(passport.session()); app.use('/', pageRouter); app.use('/auth', authRouter); app.use((req, res, next) => { const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`); error.status = 404; next(error); }); app.use((err, req, res, next) => { res.locals.message = err.message; res.locals.error = process.env.NODE_ENV !== 'production' ? err : {}; res.status(err.status || 500); res.render('error'); }); app.listen(app.get('port'), () => { console.log(app.get('port'), '번 포트에서 대기중'); }); main.html{% extends 'layout.html' %} {% block content %} <div class="timeline"> {% if user %} <div> <form id="twit-form" action="/post" method="post" enctype="multipart/form-data"> <div class="input-group"> <textarea id="twit" name="content" maxlength="140"></textarea> </div> <div class="img-preview"> <img id="img-preview" src="" style="display: none;" width="250" alt="미리보기"> <input id="img-url" type="hidden" name="url"> </div> <div> <label id="img-label" for="img">사진 업로드</label> <input id="img" type="file" accept="image/*"> <button id="twit-btn" type="submit" class="btn">짹짹</button> </div> </form> </div> {% endif %} <div class="twits"> <form id="hashtag-form" action="/hashtag"> <input type="text" name="hashtag" placeholder="태그 검색"> <button class="btn">검색</button> </form> {% for twit in twits %} <div class="twit"> <input type="hidden" value="{{twit.User.id}}" class="twit-user-id"> <input type="hidden" value="{{twit.id}}" class="twit-id"> <div class="twit-author">{{twit.User.nick}}</div> {% if not followingIdList.includes(twit.User.id) and twit.User.id !== user.id %} <button class="twit-follow">팔로우하기</button> {% endif %} <div class="twit-content">{{twit.content}}</div> {% if twit.img %} <div class="twit-img"><img src="{{twit.img}}" alt="섬네일"></div> {% endif %} </div> {% endfor %} </div> </div> {% endblock %} {% block script %} <script> if (document.getElementById('img')) { document.getElementById('img').addEventListener('change', function(e) { const formData = new FormData(); console.log(this, this.files); formData.append('img', this.files[0]); axios.post('/post/img', formData) .then((res) => { document.getElementById('img-url').value = res.data.url; document.getElementById('img-preview').src = res.data.url; document.getElementById('img-preview').style.display = 'inline'; }) .catch((err) => { console.error(err); }); }); } document.querySelectorAll('.twit-follow').forEach(function(tag) { tag.addEventListener('click', function() { const myId = document.querySelector('#my-id'); if (myId) { const userId = tag.parentNode.querySelector('.twit-user-id').value; if (userId !== myId.value) { if (confirm('팔로잉하시겠습니까?')) { axios.post(`/user/${userId}/follow`) .then(() => { location.reload(); }) .catch((err) => { console.error(err); }); } } } }); }); </script> {% endblock %}
-
해결됨Spring Boot JWT Tutorial
mysql 설정로 실습시
# server port #spring.server.port=8080 # data base spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3307/데이터베이스이름?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8 spring.datasource.username=유저 spring.datasource.password=비밀번호 # thymeleaf spring.thymeleaf.cache=false spring.jpa.database=mysql spring.jpa.database-platform= org.hibernate.dialect.MySQL8Dialect # spring data jpa spring.jpa.properties.hibernate.dialect.storage_engine=innodb spring.jpa.show-sql=true spring.jpa.open-in-view=false spring.jpa.hibernate.ddl-auto=create spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.show_sql=true spring.jpa.defer-datasource-initialization= true spring.sql.init.mode= always logging.level.org.silvernine=DEBUGplugins { id 'java' id 'org.springframework.boot' version '3.1.5' id 'io.spring.dependency-management' version '1.1.3' } group = 'NewYear' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.testng:testng:7.1.0' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' implementation 'mysql:mysql-connector-java:8.0.29' // implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.29' runtimeOnly 'mysql:mysql-connector-java' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('bootBuildImage') { builder = 'paketobuildpacks/builder-jammy-base:latest' } tasks.named('test') { useJUnitPlatform() } mysql에 정상적으로 connection이 되는 데 Entity에서 테이블 생성을 못하는 거 같습니다.따로 오류는 없고, 테이블이 생성이 안됩니다.data.sql에서 따로 테이블을 생성하는 구문을 넣으면 테이블과 컬럼값들이 제대로 들어가는 데 Entity에선 테이블을 자동으로 생성하지 못합니다.무엇이 문제일까요? ㅠㅠ
-
미해결스프링부트 시큐리티 & JWT 강의
컴파일 오류가 뜹니다.
따라 쳤는데 왜 이런 오류가 뜨는지 알고 싶습니다. 깃허브에 코드도 없는 것 같아서 질문 드립니다.
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
람다 접근 에러
너무 자주 잘문드려 죄송합니다...2023-11-23T13:10:50.588Z 50b59392-754b-4b9c-90a1-ed48e95f40e1 ERROR AccessDenied: Access Denied at throwDefaultError (/var/task/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:8:22) at /var/task/node_modules/@smithy/smithy-client/dist-cjs/default-error-handler.js:18:39 at de_GetObjectCommandError (/var/task/node_modules/@aws-sdk/client-s3/dist-cjs/protocols/Aws_restXml.js:4330:20) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /var/task/node_modules/@smithy/middleware-serde/dist-cjs/deserializerMiddleware.js:7:24 at async /var/task/node_modules/@aws-sdk/middleware-signing/dist-cjs/awsAuthMiddleware.js:14:20 at async /var/task/node_modules/@smithy/middleware-retry/dist-cjs/retryMiddleware.js:27:46 at async /var/task/node_modules/@aws-sdk/middleware-flexible-checksums/dist-cjs/flexibleChecksumsMiddleware.js:63:20 at async /var/task/node_modules/@aws-sdk/middleware-sdk-s3/dist-cjs/region-redirect-endpoint-middleware.js:14:24 at async /var/task/node_modules/@aws-sdk/middleware-sdk-s3/dist-cjs/region-redirect-middleware.js:9:20 { '$fault': 'client', '$metadata': { httpStatusCode: 403, requestId: 'S3JVT25F4WT5TH9H', extendedRequestId: 'i2FSNxeCIH5smb0tHWggtUQ7WWZIvDurOoQ4UGIZ1eVgwIPsJwrNC85V8Oh2XHVpCaFyITlXaaM=', cfId: undefined, attempts: 1, totalRetryDelay: 0 }, Code: 'AccessDenied', RequestId: 'S3JVT25F4WT5TH9H', HostId: 'i2FSNxeCIH5smb0tHWggtUQ7WWZIvDurOoQ4UGIZ1eVgwIPsJwrNC85V8Oh2XHVpCaFyITlXaaM='}이러한 에러가 발생했습니다. 찾아보니깐 s3 버컷 정책과 관련이 있는 것 같습니다.{ "Version": "2012-10-17", "Statement": [ { "Sid": "AddPerm", "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::whatsup1/*" } ]}이게 저의 s3 버캣 정책입니다.그리고 아래는 aws-upload의 index.js입니다 //이미지 리사이징 라이브러리 const sharp = require("sharp"); const { S3Client, GetObjectCommand, PutObjectCommand, } = require("@aws-sdk/client-s3"); //함수가 aws 람다에서 돌아가기 때문에 스크릿키랑 아이디를 자동으로 넣어준다 = > 아무것도 넣어줄 필요 x const s3 = new S3Client(); //람다는 3개의 매개변수를 제공하고 이 함수를 호출해준다. exports.handler = async (event, context, callback) => { const Bucket = event.Records[0].s3.bucket.name; const Key = decodeURIComponent(event.Records[0].s3.object.key); //original/리버풀.png const filename = Key.split("/").at(-1); const ext = Key.split(".").at(-1).toLowerCase(); const requiredFormat = ext === "jpg" ? "jpeg" : ext; console.log("name", filename, "ext", ext); try { const getObject = await s3.send(new GetObjectCommand({ Bucket, Key })); const buffers = []; for await (const data of getObject.Body) { buffers.push(data); } const imageBuffer = Buffer.concat(buffers); console.log("original", getObject); const resizedImage = await sharp(imageBuffer) .resize(200, 200, { fit: "inside" }) .toFormat(requiredFormat) .toBuffer(); await s3.send( new PutObjectCommand({ Bucket, Key: `thumb/${filename}`, Body: resizedImage, }) ); console.log("put", resizedImage.length); return callback(null, `thumb/${filename}`); } catch (error) { console.error(error); return callback(error); } }; 구글링 해보니깐 s3정책들이 비슷하면서 약간씩 다르던데 뭐가 맞는건지 잘 모르겠습니다..
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
람다 에러
stack": [ "Error: ", "Something went wrong installing the \"sharp\" module", "", "Cannot find module '../build/Release/sharp-linux-arm64v8.node'"이렇게 에러가 발생했는데 람다에서 함수 생성시 선택사항에 보면아키텍쳐 선택할때 제로초님은 기본적으로 선택되어있는 x86을 선택하셨고 저는 맥북에어 m2를 사용해서 arm64를 선택했는데 이거 때문에 에러가 난걸까요? 그리고 제로초님이 강의 만드실때는 node 18버전이 최신버전이였는데 지금은 20까지 나와서 20으로 했는데 이것도 문제가 될까요?
-
미해결[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지
Error: Data too long for column
req.file을 보면 아래와 같이 나옵니다.{ fieldname: 'img', originalname: 'á\x84\x89á\x85³á\x84\x8Fá\x85³á\x84\x85á\x85µá\x86«á\x84\x89á\x85£á\x86º 2023-11-22 á\x84\x8Bá\x85©á\x84\x92á\x85® 8.36.00.png', encoding: '7bit', mimetype: 'image/png', size: 156946, bucket: 'whatsup1', key: 'original/1700700649389_á\x84\x89á\x85³á\x84\x8Fá\x85³á\x84\x85á\x85µá\x86«á\x84\x89á\x85£á\x86º 2023-11-22 á\x84\x8Bá\x85©á\x84\x92á\x85® 8.36.00.png', acl: 'private', contentType: 'application/octet-stream', contentDisposition: null, contentEncoding: null, storageClass: 'STANDARD', serverSideEncryption: null, metadata: undefined, location: 'https://whatsup1.s3.ap-northeast-2.amazonaws.com/original/1700700649389_%C3%A1%C2%84%C2%89%C3%A1%C2%85%C2%B3%C3%A1%C2%84%C2%8F%C3%A1%C2%85%C2%B3%C3%A1%C2%84%C2%85%C3%A1%C2%85%C2%B5%C3%A1%C2%86%C2%AB%C3%A1%C2%84%C2%89%C3%A1%C2%85%C2%A3%C3%A1%C2%86%C2%BA%202023-11-22%20%C3%A1%C2%84%C2%8B%C3%A1%C2%85%C2%A9%C3%A1%C2%84%C2%92%C3%A1%C2%85%C2%AE%208.36.00.png', etag: '"9afb9409e1bcd41269629b6bb1100245"', versionId: undefined}제로초님은 사진 파일 확장자가 jpg로 뜨는데 저는 png로 뜹니다..s3에 저장되는 쪽이 아니라 사진을 파일로 만드는 부분에서 문제가 있는 것 같은데 어느부분에서 손을 봐야할지 잘 모르겠습니다..const { S3Client } = require("@aws-sdk/client-s3"); const multerS3 = require("multer-s3"); const s3 = new S3Client({ credentials: { accessKeyId: process.env.S3_ACCESS_KEY_ID, secretAccessKey: process.env.S3_SECRET_ACCESS_KEY, }, region: "ap-northeast-2", }); const upload = multer({ storage: multerS3({ s3, bucket: "whatsup1", key(req, file, cb) { cb(null, `original/${Date.now()}_${file.originalname}`); }, }), limits: { fileSize: 5 * 1024 * 1024 }, });그리고 추가적인 질문이 있는데 localhost로 서버를 작동시킬때 db는 잘 보이는데 lightsail로 작동시킨 db가 보이지 않습니다..mysql connection 추가 버튼 눌러서 hostname을 aws에서 제공해준 ip로 바꾸면 되는거 아닌가요?그런데 그렇게 하고 연결을 하니깐 버퍼링이 걸리면서 연결이 되지 않습니다..
-
미해결스프링부트 시큐리티 & JWT 강의
권한 처리 세션 사용
유익한 강의 감사드립니다.질문이 있습니다.권한처리를 위해 세션을 사용하게 되면서버가 여러대일 경우어떤 서버에는 권한정보가 있고어떤 서버에는 없을 수도 있지 않나요?이런 경우 스프링 시큐리티가 자동으로 알아서 처리를 해주는건가요?세션을 사용하지 않고 JWT 를 사용하는 이유중에 하나가서버가 여러대 일 경우의 세션 문제를 해결하기 위함도 있다고 하셨는데마찬가지로 서버가 여러대라면 권한처리를 위한 권한정보를 동일하게 맞춰(?) 주는 무엇인가가 필요하지 않나요?