[SPRING] 봄 보안 - 휴식 서비스에서 일반 양식 대신 json으로 자격 증명을 전송합니다.
SPRING봄 보안 - 휴식 서비스에서 일반 양식 대신 json으로 자격 증명을 전송합니다.
나는 json과 휴식 서비스를 쓰고있다. 백엔드에서는 Spring Security를 사용합니다. 나는 양식 마녀가 다음과 같이 아약스 휴식 개체와 함께 보낸다 :
{email: "admin", password: "secret"}
이제 서버에서 다음과 같이 구성합니다.
@Configuration
@EnableWebSecurity
@ComponentScan("pl.korbeldaniel.cms.server")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
private RestAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private RestAuthenticationFailureHandler authenticationFailureHandler;
@Bean
JsonAuthenticationFilter jsonAuthenticationFilter() throws Exception {
JsonAuthenticationFilter filter = new JsonAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
System.out.println("jsonAuthenticationFilter");
return filter;
}
@Bean
public RestAuthenticationSuccessHandler mySuccessHandler() {
return new RestAuthenticationSuccessHandler();
}
@Override
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("secret").roles("ADMIN");
// auth.jdbcAuthentication().
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(jsonAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
http.csrf().disable();//
http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint)//
.and().authorizeRequests()//
.antMatchers("/").permitAll()//
.antMatchers("/services/anonymous/**").permitAll()//
.antMatchers("/services/authenticated/**").authenticated()//
.and().formLogin().loginProcessingUrl("/services/anonymous/loginService/login").usernameParameter("email").passwordParameter("password")//
.successHandler(authenticationSuccessHandler)//
.and().logout().logoutUrl("/services/anonymous/loginService/logout");
// http.httpBasic();
}
}
문제는 스프링 보안이 나에게 시체로 자격증을 요구한다는 것이지만, 나는 나의 Json 객체를 받아 들일 만하다.
그래서 나는 이것에 대한 나의 자신의 인증 필터베이스를 썼다 :
@Component
public class JsonAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private boolean postOnly;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
System.out.println("attemptAuthentication");
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
UsernamePasswordAuthenticationToken authRequest = this.getUserNamePasswordAuthenticationToken(request);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
/**
* @param request
* @return
*/
private UsernamePasswordAuthenticationToken getUserNamePasswordAuthenticationToken(HttpServletRequest request) {
// TODO Auto-generated method stub
System.out.println(request);
return null;
}
}
하지만 불행히도이 필터는 작동하지 않는 것 같습니다.
로그인 폼에서 아약스 게시물 요청을 보내면 302 Found를 얻었고 다음으로 이것을 얻습니다.
Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/cms/login?error
Request Method:GET
Status Code:404 Not Found
마찬가지로 사용자 자격 증명을 확인하지 못했습니다 (원인은 양식 본문이 비어 있고 자격 증명이 json으로 변경됨). 그런 다음 로그인으로 리디렉션됩니까? 내 로그인 양식이 있기 때문에 존재하지 않는 오류입니다.
도와주세요.
편집하다
public class WebServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { SecurityConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
// return new String[] { "/" };
// return new String[] { "/cms/" };
return new String[] { "/services/*" };
}
}
@EnableWebMvc
@ComponentScan(basePackages = "pl.daniel.cms.server")
public class WebConfig extends WebMvcConfigurerAdapter {
}
해결법
-
==============================
1.getUserNamePasswordAuthenticationToken 본문을 작성하기 전까지는 작동하지 않아야합니다.
getUserNamePasswordAuthenticationToken 본문을 작성하기 전까지는 작동하지 않아야합니다.
실제로, 당신은 HttpServletRequest의 요청 본문을 읽고 Jackson 또는 다른 매핑 방법을 통해 구문 분석 한 다음 UsernamePasswordAuthenticationToken을 만들어야합니다.
Jackson을 사용하여 (Spring 버전에 따라 올바른 버전을 선택하십시오), 다음과 같은 간단한 bean을 생성 할 것입니다 :
@JsonIgnoreProperties(ignoreUnkown=true) public LoginRequest{ private String email; private String password; // getters & setters }
요청 본문을 매핑하는 데 사용합니다.
private UsernamePasswordAuthenticationToken getUserNamePasswordAuthenticationToken(HttpServletRequest request) throws IOException{ StringBuffer sb = new StringBuffer(); BufferedReader bufferedReader = null; String content = ""; LoginRequest sr = null; try { bufferedReader = request.getReader() char[] charBuffer = new char[128]; int bytesRead; while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) { sb.append(charBuffer, 0, bytesRead); } content = sb.toString(); ObjectMapper objectMapper = new ObjectMapper(); try{ sr = objectMapper.readValue(content, LoginRequest.class); }catch(Throwable t){ throw new IOException(t.getMessage(), t); } } catch (IOException ex) { throw ex; } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ex) { throw ex; } } } return new UsernamePasswordAuthenticationToken(sr.getEmail(), sr.getPassword());
}
P.D. Yo는 Post를 사용해야합니다. GET을 사용하여 요청 본문을 게시 할 수 없습니다.
from https://stackoverflow.com/questions/35724278/spring-security-send-credentials-as-json-instead-of-regular-form-in-rest-servic by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] UserDetails의 사용자 지정 구현 예제 (0) | 2019.02.16 |
---|---|
[SPRING] 싱글 사인온 + 봄 [마감] (0) | 2019.02.16 |
[SPRING] 스프링 배치를 사용하여 작업을 병렬로 실행 (0) | 2019.02.16 |
[SPRING] 로깅 뒤에서 봄 (0) | 2019.02.16 |
[SPRING] Spring은 웹 애플리케이션 외부의 디스크상의 외부 폴더에서 파일과 이미지를 가져 옵니까? (0) | 2019.02.16 |