-
0921. 회원가입정보 저장하기카테고리 없음 2023. 9. 21. 18:35
Ajax
Asynchronous 비동기
*모든 I/O 자바스크립트는 비동기 (통신)
JSON
서버로부터 데이터를 받으려면 요청을 보내야 서버가 응답을 할 때 응답 속에 데이터가 들어있다.
<보통>
1. 브라우저 창에 주소 입력
2. <a> 주소 지정
3. form = action에 주소 지정
=> 요청하면 브라우저가 페이지를 바꿔서 다시 렌더링을 해야하는 번거로움이 있다.
전체 페이지는 유지하면서 페이지변경은 안 하고(브라우저가 현재 페이지 유지)
그럼 브라우저 자체가 요청을 보낼 수는 없고(그럼 바뀜)
자바스크립트가 서버와 개별통신을 하면 (요청 & 응답) 수신한 데이터를 가공해서 동적으로 화면에서 동조작을 통해 업데이트 하는 것이다.
ex) 지도, 메일, 댓글처리
=> 거의 대부분 Ajax 기술을 내포
SignUp(회원가입)
유효성 맞다고 바로 insert할 수 없다.
직접 해야하는 작업이 있기 때문이다.
1. 유효성 검사(자동화되어있음)
2. 추가 유효성 검사 (1번의 @Valid로 기본 체크가 되지 않는 사항들) : 비밀번호 확인, 아이디 중복확인
3. 확인 후 직접 에러 추가 (@Valid 뒤에 Errors 인터페이스 객체)
- 전역 에러 : 필드에서 걸렀는데 수용할 수 없는 것들 => 로그인 시 비밀번호와 아이디가 안 맞는 경우
*reject(에러코드, 메시지)
필드 상관없으므로 필드 인자는 필요 x
- 필드 에러 : 특정 필드만
*rejectValue(필드, 에러코드, 메시지)
+) errors.hasErrors() : 전체적으로 에러가 있는지
+) errors.hasFieldErrors() : 특정 구간에 에러가 존재하는지
유효성 검사가 끝나면 실제 저장을 해야 한다. "2번"
1. Member_tbl : 비밀번호 암호화(비밀번호 인코더를 @Bean으로 등록했는데 Service에서 @Autowired로 사용하면 된다.)
2. Auth_tbl :
아바타 이미지 업로드
🖤비밀번호 확인할 때 실제 사용 예
모델 객체 설계
우리는 DB에 있는 테이블을 염두에 두고 해당 컬럼의 정보를 담을 수 있도록 모델을 설계했다.
(기존에는 signup을 있던 모델에 추가)
그래서 화면에 form을 submit했을 때 전송되면 modelAttribute로 자동으로 채워지는 기법을 사용했다.
그래서 form에서 입력받는 것과 테이블 내용이 일치한다.
그런데, form의 필드와 테이블의 컬럼이 일치하지 않는 경우가 있다.
이 경우 모델 객체를 설계할 때는 상황에 따라 맞춰야 한다.
DB에 저장을 쉽게하기 위해 DB에 맞추면 form과 일치가 어렵고, form에 맞추면 submit해서 form정보 받아들이긴 쉬우나 DB에 저장할 때 문제가 생길 수 있다.
[상황]
Password2 (비밀번호확인) : 테이블에 존재하지 않음
비밀번호 변경시 : 기존 비밀번호 / 새 비밀번호 / 새 비밀번호 확인 필요
[권장사항]
모델객체를 각자 따로 만드는 게 좋다.
DB에 맞추는 것, form에 맞추는 것 (서로 변환해서 쓰기)
DB 모델 특화 : VO
form 모델 특화, view출력 : DTO(Data transfer object) / view를 위해서 만든 모델일 때 VM(view model)이라고도 쓴다.
- Mybatis는 xml 기반 맵핑이라 XRM(xml relational mapping)이라 굳이 둘로 나누지 않아도 쓴다.
- ORM(object relational) 은 객체를 관계 테이블로 맵핑하겠다는 뜻이라 VO 객체가 자동으로 테이블에 반영이 된다.
VO 객체의 클래스명 = 테이블명/ VO객체의 필드명 = 테이블의 컬럼명 : SQL 문을 안 쓰고 객체의 메서드로 처리함
그래서 VO와 DTO를 명확히 구분짓고 변환해서 사용하도록 운영해야 한다.
DB에 회원가입 정보 저장하기
인터페이스 MemberMapper
package org.galapagos.mapper; import org.galapagos.domain.AuthVO; import org.galapagos.domain.MemberVO; public interface MemberMapper { public MemberVO read(String username); public void insert(MemberVO member); //member tbl에 대한 insert public void insertAuth(AuthVO auth);//auth tbl insert }
MemberMapper.xml
<insert id="insert"> insert into tbl_member(username, password, email) value(#{username}, #{password}, #{email}) </insert> <insert id="insertAuth" > insert into tbl_member_auth(username, auth) values(#{username}, #{auth}) </insert>
MemberServiceImpl 구현체
package org.galapagos.service; import org.galapagos.domain.AuthVO; import org.galapagos.domain.MemberVO; import org.galapagos.mapper.MemberMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import lombok.extern.log4j.Log4j; @Service @Log4j public class MemberServiceImpl implements MemberService { @Autowired MemberMapper mapper; @Autowired private PasswordEncoder pwEncoder; @Override public MemberVO get(String username) { return mapper.read(username); } @Override public void register(MemberVO member) { //1. 비밀번호 암호화 String encPassword = pwEncoder.encode(member.getPassword()); member.setPassword(encPassword); //2. tbl_member에 저장 mapper.insert(member); //3. tbl_member_auth에 저장(#{username} Foreign key 때문에 먼저 저장하면 에러) AuthVO auth = new AuthVO(member.getUsername(), "ROLE_USER"); //4. 아바타 이미지 저장 } }
*인메모리에서는 ROLE_MEMBER지만
DB 에는 ROLE_USER
SecurityController에서 호출
// DB 저장 service.register(member); return "redirect:/";
썸네일 이미지
아바타 이미지 하나 준비해서 temp 폴더에 저장
Upload 폴더에는 avatar 폴더 하나 만들기
테스트 영역에 AvatarTest
package org.galapagos.security; import org.galapagos.config.RootConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { RootConfig.class, SecurityConfig.class }) public class AvatarTest { //업로드할 디렉토리 상수영역 정하기 public static final String AVATAR_UPLOAD_DIR = "c:/upload/avatar"; @Test public void testUpload() { } }
파일 업로드 코드 추가
@Test public void testUpload() throws IOException { //파일 저장이니 예외처리 필수 String username = "unknown"; File src = new File("c:/Temp/ninja.jpg"); File dest = new File(AVATAR_UPLOAD_DIR, username + ".png"); //해당 경로에서 양식에 맞게 저장해 주는 역할 Thumbnails.of(src) .size(50, 50) .toFile(dest); }
Junit Test 해 주면 지정한 경로 폴더에 이렇게 png 확장자로 지정한 이름형식과 함께 파일이 하나 생긴다!
unknown
회원가입할 때 아바타 이미지 같이 등록되게 처리하기
ex01에서 가져오기
signup.jsp 의 form 에 추가 (인코딩 타입 지정하는 파트)
이메일 form 밑에 input 타입으로 아바타 하나 추가
여기서 avatar는 controller 에서 따로 처리할 것
name은 avatar SecurityController 의 Errors 뒤에 추가해서 받기
>> MultipartFile avatar
이제 register 할 때 아바타도 매개변수로 추가해야 함
에러가 나니, name과 이름이 같도록 추가하기
signup.jsp 에서의 name과 같도록
MemberService
MemberServiceImpl
매개변수 수정 추가로 AvatarTest에서 쓴 상수를 맨 위에 복사해 오기
destination 부분도 복사해 와서 멤버명 수정하기
파란 블록 부분 username에서 수정함 thumbnail 도 추가하고 예외 던지기
인터페이스와 안 맞아 에러가 발생하는 것이니 Controller, 인터페이스 수정
인터페이스 컨트롤러 🐲403 에러가 뜨는데 security 필터 문제이다
회원가입을 할 때..multipart form(첨부파일 같이 넣느라)이라서 csrf 토큰이 없는 걸로 해석해서 403에러가 뜨는데
csrf를 필터로 캐릭터 앞에 배치해야 하거나 이렇게 쿼리문으로 "?" 작성해야한다.
https://shinsunyoung.tistory.com/78
Spring Security로 로그인/회원가입 프로젝트
안녕하세요! 이번 포스팅에서는 Spring Security에 대해 알아보겠습니다. 🤗 Spring Security는 정말 자주 사용하는 기능이자 그만큼 중요하기 때문에 전체적인 내용을 복습할 겸 잊어버리지 않기 위해
shinsunyoung.tistory.com
signup.jsp 에 기존 hidden 삭제
action으로 csrf 토큰 추가
🐲+) 2개 이상의 update문을 실행할 때(insert 2개 등)는 transaction 처리를 해야 한다. 에러나면 rollback해야 되니
menu.jsp 에서 랜덤으로 했던 아바타 이미지 바꾸기
경로 설정
sm : 아바타 크기 (작은 아바타) 더 크면 md, big
경로에 있는 변수 : Path Variable
<!--menu.jsp--> <li class="nav-item"> <a class="nav-link" href="#"> <img src="/security/avatar/sm/${username}" class="avatar-sm" /> ${username} </a> </li>
글쓰기 버튼은 로그아웃상태에서 보이게만 하고 누르면 로그인이 필요한 서비스입니다 라고 뜨게 한다.