gpt4 book ai didi

java - Spring security-在 rest 服务中将凭据作为 json 而不是常规形式发送

转载 作者:搜寻专家 更新时间:2023-10-31 20:09:46 26 4
gpt4 key购买 nike

我正在使用 json 编写 rest 服务。对于后端,我使用 Spring Security。我有女巫用 ajax rest 对象发送的表单,如下所示:

{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();
}
}

问题是 spring 安全要求我将凭据作为正文发送,但我想 spring 接受我的 Json 对象。

所以我基于 this 编写了自己的身份验证过滤器:

@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;
}

}

但不幸的是,这个过滤器似乎不起作用。

当我从登录表单发送 ajax post 请求时,我得到 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),然后它重定向到 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 {
}

最佳答案

嗯,在您编写 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());

PD你必须使用 Post,你将永远无法使用 GET 发布请求正文

关于java - Spring security-在 rest 服务中将凭据作为 json 而不是常规形式发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35724278/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com