Spring Security(7)
您好,我是湘王,这是我的云海天,欢迎您来,欢迎您再来~
有时某些业务或者功能,需要在用户请求到来之前就进行一些判断或执行某些动作,就像在Servlet中的FilterChain过滤器所做的那样,Spring Security也有类似机制。Spring Security有三种增加过滤器的方式:addFilterBefaore()、 addFilterAt()和addFilterAfter(),也可以disable掉默认的过滤器,例如:
1、http.logout().disable();或者http.headers().disable();
2、用自定义过滤器http.addFilterAt(new MyLogoutFilter(), LogoutFilter.class)替换
Spring Security的官方列出了过滤器调用顺序,具体可参考官方网站。
Spring Security已经定义好,可以直接使用的过滤器有下面这些:
比如,现在的互联网应用都有一个通用的「业务规则」是:在执行所有功能接口的时候都要检查确认接口签名的有效性。所谓接口签名其实就是一套进入准则,客户端按照服务器规定的方式向服务器证明自己确实是某个网站的用户。
那么,在Spring Security里面可以这么干:
/** * 自定义拦截过滤器 * * @author 湘王 */ @Component public class CustomInterceptorFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException { // 保存参数=参数值对 Map<String, String> mapResult = new HashMap<String, String>(); // 请求中的参数 Enumeration<String> em = request.getParameterNames(); while (em.hasMoreElements()) { String paramName = em.nextElement(); String value = request.getParameter(paramName); mapResult.put(paramName, value); } // 验证参数,只要有一个不满足条件,立即返回 if (null == mapResult.get("platform") || null == mapResult.get("timestamp") || null == mapResult.get("signature")) { response.getWriter().write("api validate failure"); } Object result = null; String platform = mapResult.get("platform"); String timestamp = mapResult.get("timestamp"); String signature = mapResult.get("signature"); // 后端生成签名:platform = "xiangwang" timestamp = "159123456789" signature = "" String sign = DigestUtils.md5DigestAsHex((platform + timestamp).getBytes()); validateSignature(signature, sign, request, response, chain); } // 验证签名 private void validateSignature(String signature, String sign, ServletRequest request, ServletResponse response, FilterChain chain) throws IOException { if (signature.equalsIgnoreCase(sign)) { try { // 让调用链继续往下执行 chain.doFilter(request, response); } catch (Exception e) { response.getWriter().write("api validate failure"); } } else { response.getWriter().write("api validate failure"); } } public static void main(String[] args) { // 这里的验证签名算法可以随便自定义实现(guid = "0" platform = "web" timestamp = 156789012345) // 下面的代码只是伪代码,举个例子而已 String sign = ""; if(StringUtils.isBlank(guid)) { // 首次登录,后端 platform + timestamp + "xiangwang" 生成签名 sign = DigestUtils.md5DigestAsHex((platform + timestamp + "xiangwang").getBytes()); validateSignature(signature, sign, request, response, chain); } else { // 不是首次登录,后端 guid + platform + timestamp 生成签名 // 从Redis拿到token,这里不实现 // Object object = service.getObject("token#" + guid); Object object = "1234567890abcdefghijklmnopqrstuvwxyz"; if(null == object) { response.getWrite().write("token expired"); } else { token = (String) obejct; // 验证sign sign = DigestUtils.md5DigestAsHex((platform + timestamp + "xiangwang").getBytes()); validateSignature(signature, sign, request, response, chain); } } System.out.println(DigestUtils.md5DigestAsHex(("web" + "156789012345").getBytes())); } }