- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在使用 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/
当给定两个 bool 参数时,^ 运算符执行异或,例如 true ^ true == false true ^ false == true false ^ true == true false ^ f
我需要下载一个文件(例如: https://www.betaseries.com/srt/391160 )所以我在网上找到了不同的方法: def download(String remoteUrl,
可以说,我们正在计算考试成绩的平均值: 起始考试成绩:75、80、92、64、83、99、79 平均值= 572/7 = 81.714 ... 现在给出81.714,如果您不知道初始测试分数,是否可以
我和一个 friend 正在争论线程池中的线程数应该是处理器计数+ 1还是仅仅是处理器计数。 我之所以选择处理器数量,是因为每个处理器可以分配偶数个线程,而他选择处理器数量+ 1是因为他认为这将帮助他
我已经养成了尽可能使用闭包来代替常规方法的习惯,即使我不需要访问自由变量。所以,我将使用这个: def addNumbers = { 左、右 -> 左 + 右 } ..而不是这个: def addNu
我对 Groovy 非常陌生,我正在尝试《Groovy in Action》书中的这个示例。我有这个 fibonacci.groovy 程序,当尝试使用 java 命令运行该程序时,我收到 NoCla
我有 3 个 TextView 。我需要将它们的权重设置为 Light、Regular 和 Condensed。有人可以帮助我了解如何在 Android 中实现这一点吗? 最佳答案 在 TextVie
如果用户启动我的应用程序并最初选择不允许位置服务,我想通过 UIAlertMessage 提示用户重新考虑(“更新”和“不,谢谢。”)。 “不,谢谢。”这将是一个简单的取消,我希望“更新”将它们直接链
如何在 groovy 中显示一个值是真还是假?我使用 Eclipse 作为我的 IDE。 assert 4 * ( 2 + 3 ) - 6 == 14 //integers only 而且我也
我的问题与“多处理器编程的艺术”一书有关。第4章介绍安全/常规/原子寄存器及其实现。 以下是安全多读取器单写 boolean 寄存器的以下实现,该寄存器基于安全单读取器单写 boolean 寄存器,被
使用下面的代码来保存 float 的值 domainInstance.standardScore = params["standardScore"] as float 在这种情况下,我的输入是 17.
使用下面的代码来保存 float 的值 domainInstance.standardScore = params["standardScore"] as float 在这种情况下,我的输入是 17.
在iOS的about部分中,它具有有关设备的大量信息。 我和我可以访问此信息吗? 我想快速获取settings -> General -> About的数据。在iOS中获得相同的价格是否可行? 最佳答
我正在开发Windows服务,它将承载两件事: WCF服务 用于定期作业执行的“常规” Windows服务(使用Quartz.net) 因此,基本上,一个应用程序(可执行)承载这两种服务类型。 这两种
在mysql中,我有一个名为users的表,其中包含系统中的用户列表... id | name | surname | active ____________________________ 1
所以我在 Debian 服务器上设置了一个 MySQL 数据库,并且它在 phpMyAdmin 客户端上运行良好。我目前正在开发一个项目,编写一个 Java 服务器,该服务器能够通过 JDBC 连接使
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
前两天考试了,其中一道题是把@前面的字母换成新的名字 所以在试卷中我们有 array = "toto@yahoo.com","mimi@yahoo.com".soso@yahoo.com"所以我们应该
大家好 如果字符串语法如下,我如何从字符串中获取数字(正数): t_def_type_id_2 t_def_type_id_22 t_def_type_id_334 所以,在第一个字符串中我想得到 1
我正在寻找不会在内核中阻塞的文件描述符类型。我知道我可以使用 fstat(2) 但 fstat 还会给我各种元数据信息(访问时间等),这些信息可能会阻塞任意时间(特别是在网络文件系统上)。 编辑:我正
我是一名优秀的程序员,十分优秀!