mas*_*y88 5 java rest spring json web-services
我正在rest与一起写服务json。对于后端,我使用Spring Security。我有形式巫婆发送与ajax其余对象,如下所示:
{email: "admin", password: "secret"}
Run Code Online (Sandbox Code Playgroud)
现在在服务器上,我的配置如下:
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
问题是春季安全要求我发送凭据作为正文,但是我想春季接受我的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;
}
}
Run Code Online (Sandbox Code Playgroud)
但不幸的是,此过滤器似乎不起作用。
当我从登录表单发送ajax发布请求时,我得到了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
Run Code Online (Sandbox Code Playgroud)
就像那里没有验证用户凭据(因为表单主体为空,并且凭据作为json)一样,然后将其重定向到login?error不存在的原因,因为我有自己的登录表单。
请帮忙。
编辑
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 {
}
Run Code Online (Sandbox Code Playgroud)
好吧,在您编写getUserNamePasswordAuthenticationToken主体之前,它不能工作。
实际上,您必须读取 HttpServletRequest 的请求正文,通过 Jackson 或任何其他映射方式对其进行解析,并使用它创建 UsernamePasswordAuthenticationToken。
使用 Jackson(根据您的 Spring 版本选择正确的版本),我将创建一个像这样的简单 bean:
@JsonIgnoreProperties(ignoreUnkown=true)
public LoginRequest{
private String email;
private String password;
// getters & setters
}
Run Code Online (Sandbox Code Playgroud)
使用它来将它映射到请求正文:
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());
Run Code Online (Sandbox Code Playgroud)
}
PD Yo 必须使用 Post,您将永远无法使用 GET 发布请求正文
| 归档时间: |
|
| 查看次数: |
3730 次 |
| 最近记录: |