Spring安全性 - 在休息服务中以json而不是常规形式发送凭据 [英] Spring security- Send credentials as json instead of regular form in rest service
问题描述
我正在用 json
写 rest
服务。对于后端,我使用 Spring Security
。我有一个带有ajax rest对象的女巫发送如下:
I am writing rest
service with json
. For backend I use Spring Security
. I have form witch sends with ajax rest object as follow:
{email: "admin", password: "secret"}
现在在服务器上我的配置如下:
Now on the server I have configuration as follow:
@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();
}
}
问题是Spring安全要求我发送凭证作为正文,但我想接受我的Json对象。
Problem is that spring security demands from me to send credentials as body, but I would like to spring accept my Json object.
所以我基于这个:
@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;
}
}
但不幸的是这个过滤器似乎没有工作。
But unfortunatelly this filter seems to not work.
当我从登录表单发送ajax post请求时,我收到 302 Found
然后我得到了这个:
When I send ajax post request from login form, I am getting 302 Found
and then I am getting this:
Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/cms/login?error
Request Method:GET
Status Code:404 Not Found
赞无法验证用户凭证(导致表单正文为空,凭据作为json),然后它重定向到登录?错误
这不存在因为我是我的自己的登录表格。
Like there fail to validate user credential (cause form body is empty and credentials goes as json), and then it redirect to login?error
which doesn't exist cause I've my own login form.
请帮忙。
编辑
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 {
}
推荐答案
嗯,它在你写 getUserNamePasswordAuthenticationToken 正文之前一定不能工作。
Well, it must not work until you write the getUserNamePasswordAuthenticationToken body.
实际上,你必须阅读HttpServletRequest的请求主体,通过Jackson解析它或任何其他映射方式并使用它创建UsernamePasswordAuthenticationToken。
Actually, you must read the request body of the HttpServletRequest, parse it through Jackson or any other mapping way and create with it the UsernamePasswordAuthenticationToken.
使用Jackson(根据你的Spring版本选择合适的版本),我会创建一个这样的简单bean:
Using Jackson (choose the right version depending on your Spring version), I would create a simple bean like this:
@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。哟必须使用Post,你永远无法使用GET
P.D. Yo must use Post, you will never be able to post a request-body using GET
这篇关于Spring安全性 - 在休息服务中以json而不是常规形式发送凭据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!