这里给出详细的“Spring security 自定义过滤器实现Json参数传递并兼容表单参数(实例代码)”攻略:
1. 概述
当我们用 Spring Security 来进行用户认证和授权时,为了保证安全性,一般使用 POST 请求提交表单参数,而不能使用 GET 请求进行参数传递。但是在某些情况下,我们需要通过 Json 参数来进行传递,此时就需要用到自定义过滤器来实现这一过程。下面给出一条完整的攻略:
2. 自定义过滤器
我们先定义一个名为 JsonParamsFilter
的自定义过滤器,实现 doFilter
方法。在 doFilter
方法中,我们对请求的 Content-Type 进行判断,如果是 application/json,则说明是 Json 参数,需要特殊处理;否则,就是普通的表单参数,可以继续执行之后的过滤器。
public class JsonParamsFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if ("application/json".equals(request.getContentType())) {
JsonParamsServletRequestWrapper jsonParamsServletRequestWrapper = new JsonParamsServletRequestWrapper(request);
filterChain.doFilter(jsonParamsServletRequestWrapper, response);
} else {
filterChain.doFilter(request, response);
}
}
}
其中 JsonParamsServletRequestWrapper
继承了 HttpServletRequestWrapper
,并且对其中的 getParameter 方法进行了覆盖,使它能够正确获取 Json 格式的参数值。
public class JsonParamsServletRequestWrapper extends HttpServletRequestWrapper {
private final Map<String, String[]> parameterMap;
public JsonParamsServletRequestWrapper(HttpServletRequest request) {
super(request);
parameterMap = new HashMap<>();
try {
InputStream stream = request.getInputStream();
byte[] requestBody = IOUtils.toByteArray(stream);
JSONObject jsonObject = new JSONObject(new String(requestBody, request.getCharacterEncoding()));
Iterator<String> iterator = jsonObject.keys();
while (iterator.hasNext()) {
String key = iterator.next();
String value = jsonObject.get(key).toString();
parameterMap.put(key, new String[]{value});
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String getParameter(String name) {
String[] values = getParameterValues(name);
if (values == null) {
return null;
}
return values[0];
}
@Override
public String[] getParameterValues(String name) {
return parameterMap.get(name);
}
}
3. 配置 Spring Security
我们在 Spring Security 的配置文件中加入 JsonParamsFilter
过滤器,并将它放在 UsernamePasswordAuthenticationFilter
之前,这样就能够在用户认证之前对 Json 参数进行处理了。以下是完整的 Spring Security 配置文件的示例代码:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login").permitAll().anyRequest().authenticated().and()
.formLogin().loginProcessingUrl("/login").and()
.addFilterBefore(new JsonParamsFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("admin").roles("ADMIN")
.and()
.withUser("user").password("user").roles("USER");
}
}
4. 示例代码
接下来给出两条示例代码,分别是使用 Curl 和 Java 代码发送 Json 参数的示例。我们按照上述配置文件中的配置,发送包含用户名和密码的 Json 参数,实现用户认证。
4.1 使用 Curl 发送 Json 参数
curl -X POST http://localhost:8080/login -H "Content-Type: application/json" -d '{"username":"admin", "password":"admin"}'
4.2 使用 Java 代码发送 Json 参数
public static void main(String[] args) throws Exception {
String url = "http://localhost:8080/login";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
String jsonString = "{\"username\":\"admin\", \"password\":\"admin\"}";
byte[] input = jsonString.getBytes("utf-8");
os.write(input, 0, input.length);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
}
5. 总结
通过以上的攻略,我们实现了 Spring Security 自定义过滤器来处理 Json 参数,使之能够兼容表单参数进行用户认证。在实际项目中,我们可以根据具体需求进行配置,使之更好地适应自己的业务场景。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring security 自定义过滤器实现Json参数传递并兼容表单参数(实例代码) - Python技术站