我正在尝试更改JHipster,以便它使用JSON对象而不是表单参数进行身份验证。我已经设法为它的JWT身份验证机制实现了这一点。现在,我想对其他身份验证选项执行此操作。
有没有一种简单的方法可以改变Spring security的默认安全配置来实现这一点?以下是JHipster现在使用的内容:
.and()
.rememberMe()
.rememberMeServices(rememberMeServices)
.rememberMeParameter("remember-me")
.key(env.getProperty("jhipster.security.rememberme.key"))
.and()
.formLogin()
.loginProcessingUrl("/api/authentication")
.successHandler(ajaxAuthenticationSuccessHandler)
.failureHandler(ajaxAuthenticationFailureHandler)
.usernameParameter("j_username")
.passwordParameter("j_password")
.permitAll()我想将以下内容作为JSON而不是表单参数发送:
{username: "admin", password: "admin", rememberMe: true}发布于 2019-01-20 04:21:19
我只是需要一些非常相似的东西,所以我写了它。
这使用了Spring Security4.2,WebSecurityConfigurationAdapter。在那里,我没有使用...formLogin()...,而是编写了一个自己的配置器,该配置器在可用时使用JSON,如果没有则缺省为Form (因为我需要这两个功能)。
我从org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer和org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter复制了所有需要出现的东西(但我并不关心),那里的源代码和文档对我帮助很大。
你也有可能需要复制其他函数,但原则上应该这样做。
最后是实际解析JSON的过滤器。代码示例是一个类,因此可以直接复制。
/** WebSecurityConfig that allows authentication with a JSON Post request */
@Configuration
@EnableWebSecurity(debug = false)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// resources go here
@Override
protected void configure(HttpSecurity http) throws Exception {
// here you will need to configure paths, authentication provider, etc.
// initially this was http.formLogin().loginPage...
http.apply(new JSONLoginConfigurer<HttpSecurity>()
.loginPage("/authenticate")
.successHandler(new SimpleUrlAuthenticationSuccessHandler("/dashboard"))
.permitAll());
}
/** This is the a configurer that forces the JSONAuthenticationFilter.
* based on org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer
*/
private class JSONLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
AbstractAuthenticationFilterConfigurer<H, JSONLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> {
public JSONLoginConfigurer() {
super(new JSONAuthenticationFilter(), null);
}
@Override
public JSONLoginConfigurer<H> loginPage(String loginPage) {
return super.loginPage(loginPage);
}
@Override
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
return new AntPathRequestMatcher(loginProcessingUrl, "POST");
}
}
/** This is the filter that actually handles the json
*/
private class JSONAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
protected String obtainPassword(JsonObject obj) {
return obj.getString(getPasswordParameter());
}
protected String obtainUsername(JsonObject obj) {
return obj.getString(getUsernameParameter());
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
if (!"application/json".equals(request.getContentType())) {
// be aware that objtainPassword and Username in UsernamePasswordAuthenticationFilter
// have a different method signature
return super.attemptAuthentication(request, response);
}
try (BufferedReader reader = request.getReader()) {
//json transformation using javax.json.Json
JsonObject obj = Json.createReader(reader).readObject();
String username = obtainUsername(obj);
String password = obtainPassword(obj);
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
username, password);
return this.getAuthenticationManager().authenticate(authRequest);
} catch (IOException ex) {
throw new AuthenticationServiceException("Parsing Request failed", ex);
}
}
}
}发布于 2016-02-29 20:09:23
我做过这样的事情。这个解决方案并不难,但我做了一个主要基于UserNamePasswordAuthenticationFilter的自定义安全筛选器的技巧。
实际上,您应该重写attemptAuthentication方法。仅仅覆盖obtainPassword和obtainUsername可能还不够,因为您希望读取请求正文,并且必须立即为这两个参数执行此操作(如果您没有创建一种多读HttpServletRequest包装器)
解决方案必须是这样的:
public class JsonUserNameAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
//[...]
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
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);
}
//[...]
protected UserNamePasswordAuthenticationToken(HttpServletRequest request){
// here read the request body and retrieve the params to create a UserNamePasswordAuthenticationToken. You may use jackson of whatever you like most
}
//[...]
}然后您必须对其进行配置。对于这种复杂的配置,我总是使用基于xml的配置,
<beans:bean id="jsonUserNamePasswordAuthenticationFilter"
class="xxx.yyy.JsonUserNamePasswordAuthenticationFilter">
<beans:property name="authenticationFailureHandler>
<beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<!-- set the failure url to a controller request mapping returning failure response body.
it must be NOT secured -->
</beans:bean>
</beans:property>
<beans:property name="authenticationManager" ref="mainAuthenticationManager" />
<beans:property name="authenticationSuccessHandler" >
<beans:bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<!-- set the success url to a controller request mapping returning success response body.
it must be secured -->
</beans:bean>
</beans:property>
</beans:bean>
<security:authentication-manager id="mainAuthenticationManager">
<security:authentication-provider ref="yourProvider" />
</security:authentication-manager>
<security:http pattern="/login-error" security="none"/>
<security:http pattern="/logout" security="none"/>
<security:http pattern="/secured-pattern/**" auto-config='false' use-expressions="false"
authentication-manager-ref="mainAuthenticationManager"
create-session="never" entry-point-ref="serviceAccessDeniedHandler">
<security:intercept-url pattern="/secured-pattern/**" access="ROLE_REQUIRED" />
<security:custom-filter ref="jsonUserNamePasswordAuthenticationFilter"
position="FORM_LOGIN_FILTER" />
<security:access-denied-handler ref="serviceAccessDeniedHandler"/>
<security:csrf disabled="true"/>
</security:http>您可以创建一些额外的对象作为拒绝访问处理程序,但这是最简单的部分
https://stackoverflow.com/questions/35687148
复制相似问题