PasswordEncoder
으아아아....
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("{noop}pw")
.roles("USER")
.and()
.withUser("admin")
.password("{noop}pw")
.roles("ADMIN", "USER");
}
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for
the id "null"
위에 에러 해결법, {noop}으로 해결
여기서, noop는 Spring Security에서 텍스트 그대로 비밀번호로 인식하게 해줍니다. {noop} 또는 비밀번호 암호화 둘중 하나는 해줘야함
이유 : PasswordEncoder 를 설정하지 않아서였다. Spring boot 는 PasswordEncoder 를 설정해 주지않으며, 이부분은 개발자가 직접 등록 해야한다
WebSecurityConfig.java
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
리턴되는 오브젝트를 IoC로 등록해줌, 이제 어디서든 쓸 수 있음
제어의 역전, 개발자가 제어 하던것을 스프링 컨테이너가 대신 해줌 덕분에 우리는 new를 선언 하지 않아도 됨
class : BCryptPasswordEncoder 비밀번호를 암호화 하는 메서드
Controller.java
@PostMapping("/join")
public String join(@ModelAttribute MainDto dto, @RequestParam HashMap<String, String> params) {
logger.info("회원가입 경로" + dto);
logger.info("입력 값" + params);
dto.setRole("USER"); //USER 강제로 입력
// 비밀번호 암호화 시작
String pw = dto.getPw();
String encpw = bCryptPasswordEncoder.encode(pw);
dto.setPw(encpw);
service.join(dto); // 비밀번호 암호화를 시켜보자! 안하면 시큐리티 사용x
return "redirect:/loginForm";
}
생긴 문제
Potsmapping 인식이 되질 않아서 @RequstMappin을 씀
이런..젠장 왜?
@PostMapping 썼을때 에러가 떨어진 이유 :
시큐리티의 csrf 때문 csrf 공격? 사용자의 의지와 무관하게 공격자의 의도대로 서버에 특정 요청을 함 그니까.. submit 할때 "안녕"을 분명 전송했지만 "광고"가 대신 들어오는 것 이것을 막기 위해
CSRF Token을 사용 CSRF Token : 서버에 들어온 요청이 실제 서버에서 허용한 요청이 맞는지 확인하기 위한 토큰 CSRF방어 기능은 Spring Security 3.2.0 이후부터 지원 @EnableWebSecurity 어노테이션은 기본적으로 CSRF 방어 기능 활성화 비활성화 시키고 싶으면configure(HttpSecurity http) 에 csrf().disable() 을 추가해주자
이 설정을 적용할때 post 방식의 데이터에는 토큰 값이 있어야 한다. REST API같은 경우엔 공격을 받지 않으니 비활성화 시켜주자
WebSecurityConfig.java 에 추가하기
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//join을 사용하기 위함 (post를 사용하기 위함)
.csrf().disable()
}
MainService.java
@Service
public class MainService {
//logger 찍기 위함
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private MainDao mapper;
public int execute(Model model) {
List<MainDto> testDto = mapper.selectMember();
// system.out 쓰지 않기
logger.info("경로 : " + testDto);
model.addAttribute("test", testDto);
return 0;
}
public int join(MainDto dto) {
return mapper.join(dto);
}
}
MainDao.java
public int join(MainDto dto);
MainDto.java
private String member_id;
private String pw;
private String name;
private String role;
public String getMember_id() {
return member_id;
}
public void setMember_id(String member_id) {
this.member_id = member_id;
}
public String getPw() {
return pw;
}
public void setPw(String pw) {
this.pw = pw;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
joinForm.jsp
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원가입 페이지</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<hr/>
<form action="join" method="post">
<input type="text" name="member_id" placeholder="Username"/> <br/>
<input type="password" name="pw" placeholder="Password"/> <br/>
<input type="text" name="name" placeholder="name"/> <br/>
<button>회원가입</button>
</form>
</body>
</html>