前言
这是我第一次尝试过滤器,要小心。
项目介绍
我正在尝试为我们的一些应用程序最终确定SSO的构建,而且似乎步履维艰。我尝试连接的Webapp使用“身份验证”标头来确定应用程序内的用户凭据。我构建了一个Filter,希望在将标头传递到Web应用程序之前对其进行设置。
问题
该代码通过Eclipse验证,编译,加载到Tomcat,然后传递到Webapp。唯一缺少的是Authentication标头。
我想念/做错了什么?
AuthenticationFilter源
package xxx.xxx.xxx.xxx.filters; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import xxx.xxx.xxx.ConfigFile; import xxx.xxx.xxx.Console; import xxx.xxx.xxx.FalseException; import xxx.xxx.activity.EncryptUtil; public class AuthenticationFilter implements Filter { public ConfigFile config; public void init(FilterConfig arg0) throws ServletException { config = new ConfigFile("C:/config.properties"); } public void doFilter(ServletRequest sRequest, ServletResponse sResponse, FilterChain filterChain) throws IOException, ServletException { Console.debug("AuthenticationFilter.doFilter() triggered."); ServletRequestWrapper request = new ServletRequestWrapper((HttpServletRequest) sRequest); HttpServletResponse response = (HttpServletResponse) sResponse; HttpSession session = request.getSession(); Cookie cookie = null; try { if (request.getParameter("logout") != null) { session.invalidate(); throw new FalseException("Logout recieved"); } String auth = request.getHeader("Authorization"); if (auth == null) { Console.debug("Authorization Header not found."); // get cookie --COOKIE NAME-- Cookie[] cookies = request.getCookies(); if (cookies == null) { throw new FalseException("Cookies not set."); } for (int i = 0; i < cookies.length; i++) { if (cookies[i].getName().equals(config.getProperty("authentication.cookie.name"))) { cookie = cookies[i]; } } if (cookie == null) { throw new FalseException("Cannot find Cookie (" + config.getProperty("authentication.cookie.name") + ") on Client"); } Console.debug("Cookie (" + config.getProperty("authentication.cookie.name") + ") found on Client. value="+cookie.getValue()); String decToken = decryptToken(cookie.getValue()); Console.debug("Decrypted Token: "+decToken); Console.debug("Setting Authorization Header..."); request.setAttribute("Authorization", decToken); request.addHeader("Authorization", decryptToken(cookie.getValue())); Console.debug("Authorization Header set."); Console.debug("Validating Authorization Header value: "+request.getHeader("Authorization")); } }catch (FalseException e) { Console.msg(e.getMessage() + ", giving the boot."); response.sendRedirect(config.getProperty("application.login.url")); } catch (Exception e) { Console.error(e); } Console.debug("AuthenticationFilter.doFilter() finished."); filterChain.doFilter(request, response); } public void destroy() { } private String decryptToken(String encToken) { String token = null; token = EncryptUtil.decryptFromString(encToken); return token; } }
web.xml源
<web-app> <filter> <filter-name>AuthenticationFilter</filter-name> <display-name>AuthenticationFilter</display-name> <description></description> <filter-class>com.xxx.xxx.xxx.filters.AuthenticationFilter</filter-class> </filter> <filter-mapping> <filter-name>AuthenticationFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> ... </web-app>
ServletRequestWrapper源
package com.xxx.xxx.xxx.filters; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; public class ServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper { public ServletRequestWrapper(HttpServletRequest request) { super(request); headerMap = new HashMap(); } private Map headerMap; public void addHeader(String name, String value) { headerMap.put(name, new String(value)); } public Enumeration getHeaderNames() { HttpServletRequest request = (HttpServletRequest) getRequest(); List list = new ArrayList(); for (Enumeration e = request.getHeaderNames(); e.hasMoreElements();) { list.add(e.nextElement().toString()); } for (Iterator i = headerMap.keySet().iterator(); i.hasNext();) { list.add(i.next()); } return Collections.enumeration(list); } public String getHeader(String name) { Object value; if ((value = headerMap.get("" + name)) != null) return value.toString(); else return ((HttpServletRequest) getRequest()).getHeader(name); } }
调试日志
LoginServlet.doGet() triggered. [DEBUG] : Authenticate.isClientLoggedIn() triggered. xxx url : https://xxx.xxx.xxx/xxx/home.action [DEBUG] : Authenticate.isClientLoggedIn() status code: 401 Unauthorized User. Client IS NOT logged in. -- Fill out Login Form, submit -- LoginServlet.doPost() triggered. [DEBUG] : Authenticate.isClientLoggedIn() triggered. xxx url : https://xxx.xxx.xxx./xxx/home.action [DEBUG] : Authenticate.isClientLoggedIn() status code: 401 Unauthorized User. Client IS NOT logged in. Client (--USERID--) attempting basic authentication with password(--PASSWORD--). [DEBUG] : BasicAuthentication.touch(http://localhost:PORT/vu/loginCheck.html, --USERID--, --PASSWORD--) triggered. [DEBUG] : BasicAuthentication.touch() response code: 200 Client (--USERID--) has been logged IN. Client (--USERID--) basic authentication finished, Client is logged in. Client (--USERID--) logged in successfully. [DEBUG] : Cookie (xxx_token) Set: 1e426f19ebdfef05dec6544307addc75401ecdc908a3c7e6df5336c744--SECRET-- [DEBUG] : Redirecting client to https://xxx.xxx.xxx/xxx/home.action -- Redirected to webapp, filter recieves -- [DEBUG] : AuthenticationFilter.doFilter() triggered. [DEBUG] : Authorization Header not found. << Initical check to see if user is already logged in to site [DEBUG] : Cookie (xxx_token) found on Client. value=1e426f19ebdfef05dec6544307addc75401ecdc908a3c7e6df5336c744--SECRET-- [DEBUG] : Decrypted Token: Basic --SECRET-- [DEBUG] : Setting Authorization Header... [DEBUG] : Authorization Header set. [DEBUG] : Validating Authorization Header value: Basic --SECRET-- << Value matches Decrypted Token [DEBUG] : AuthenticationFilter.doFilter() finished. -- Web Application errors out, unable to find Authorization header
谢谢你的帮助。
我要添加一个新答案,因为它是完全不同的。
我在系统上进行了测试。我复制了代码,转储了cookie测试,并编写了一个简单的Servlet为我转储。
而且效果很好,除了一个警告。
我不知道您的应用程序如何使用它。但是您的ServletRequestWrapper工具实现了getHeaderNames,getHeader但是,它并没有实现getHeaders。我曾经getHeaders尝试转储请求时遇到了这个问题,当然,缺少授权。
ServletRequestWrapper
getHeaderNames
getHeader
getHeaders
因此,您可能需要仔细查看代码,看看是否确实没有使用getHeaders。如果是这样,它将“正常工作”,但完全跳过您已完成的工作,从而错过您的Authorization标头。
这是我的实现,对我有用。
@Override public Enumeration getHeaders(String name) { Enumeration e = super.getHeaders(name); if (e != null && e.hasMoreElements()) { return e; } else { List l = new ArrayList(); if (headerMap.get(name) != null) { l.add(headerMap.get(name)); } return Collections.enumeration(l); } }