Java Web使用Filter过滤器进行统一的访问权限验证

安全是每个web程序必须考虑的问题,安全很重要的一部分就是身份验证。咱们能够将身份验证写成一个类,而后在每一个功能模块实现的时候调用,可是即便你只须一句代码调用身份验证,当你的项目有几百个功能模块的时候,这也是一个不小的工做,说不定有时候还会忘记。

Filter 技术是 servlet 2.3 新增长的功能,它使用户能够改变一个request 和修改一个 response. Filter 不是一个 servlet, 它不能产生一个 response, 它可以在一个 request 到达 servlet 以前预处理 request, 也能够在离开 servlet 时处理 response. 换种说法 ,filter 实际上是一个 ”servlet chaining”(servlet 链 ). 一个 filter 包括 :
  1. 在 servlet 被调用以前截获 ;

  2. 在 servlet 被调用以前检查 servlet request;

  3. 根据须要修改 request 头和 request 数据 ;

  4. 根据须要修改 response 头和 response 数据 ;

  5. 在 servlet 被调用以后截获 .

具体的在这里很少介绍。用Filter能够作到不少事情,好比经常使用的SetCharacterEncodingFilter能够统一解决编码问题。总之那些能够统一进行的“预处理”工做就能够用Filter来作。若是咱们用Filter来进行统一的身份验证,那样在功能模块代码中就不用管什么权限了。

大体思路是:定义访问URI及其所需权限,在会话中存储用户所具备的权限,每次访问的时候 根据URI找到所需的权限,而后检查用户是否是知足全部权限要求。若是知足,放行(chain.doFilter(request, response);),若是不知足,拦截(response.sendError(404);)。

实现
AccessIdentity.java

/**
* 用户身份权限类
*
* @author wenjianwzz
*
*/
public class AccessIdentity {
UserEntity user;
Date login;
Date lastActive;
Date createTime;
String ip;
List<String> tips = new ArrayList<String>();
HashMap<String, Boolean> privilege;
HashMap<String, Object> attribute = new HashMap<String, Object>();

public AccessIdentity(String ip) {
lastActive = createTime = new Date();
this.ip = ip;
refreshPrivilege();
}

private void refreshPrivilege() {
if (privilege == null) {
privilege = new HashMap<String, Boolean>();
}
privilege.clear();
privilege.put("public", true);
if (user != null) {
privilege.put("login", true);
List<String> p = user.getPrivilege();
if (p != null)
for (int i = 0; i < p.size(); i++) {
privilege.put(p.get(i), true);
}
}
}

public void notifyActive() {
lastActive = new Date();
}

public void notifyLogout() {
UserManageService.getInstance().unregisterLogin(user.getUsername());
user.notifyLogout();
login = null;
refreshPrivilege();
}

synchronized protected void logout() {
user.notifyLogout();
login = null;
refreshPrivilege();
}

public void notifyLogin(UserEntity user) {
if (!user.hasLogin())
return;
this.user = user;
login = new Date();
UserManageService.getInstance().registerLogin(user.getUsername(), this);
refreshPrivilege();
}

public UserEntity getUser() {
return user;
}

public boolean isHasLogin() {
if (user == null)
return false;
return user.hasLogin();
}

public Date getLoginTime() {
return login;
}

public Date getLastActive() {
return lastActive;
}

public Date getCreateTime() {
return createTime;
}

public String getIp() {
return ip;
}

public List<String> getTips() {
return tips;
}

public boolean hasThisPrivilege(String key) {
Boolean p = privilege.get(key);
if (p == null)
return false;
return p;
}

public void setAttribute(String name, Object value) {
attribute.put(name, value);
}

public Object getAttribute(String name) {
return attribute.get(name);
}

public String getTips(int index) {
return tips.get(index);
}

public int getTipsNumber() {
return tips.size();
}

public void addTips(String tips) {
this.tips.add(tips);
}

@Override
public int hashCode() {
if (user.getUsername() == null)
return -1;
return user.getUsername().hashCode();
}

}


Access.java URI-权限类

String path;
List<List<String>> privilege;

public Access(String path) {
this.path = path;
privilege = new ArrayList<List<String>>();
privilege.add(new ArrayList<String>());
}

public Access addPrivilege(String p, int g) {
while (g >= privilege.size()) {
privilege.add(new ArrayList<String>());
}
privilege.get(g).add(p);
return this;
}

public Access removePrivilege(String p) {
privilege.remove(p);
return this;
}

public boolean validate(AccessIdentity id) {
int j;
for (int i = 0; i < privilege.size(); i++) {
for (j = 0; j < privilege.get(i).size(); j++) {
if (!id.hasThisPrivilege(privilege.get(i).get(j))) {
break;
}
}
if (j == privilege.get(i).size() && j > 0) {
return true;
}
}
return false;
}


AccessAnalyst.java 权限分析

public class AccessAnalyst {
static String filepath;

HashMap<String, Access> map;

private static AccessAnalyst instance;

public boolean check(String url,AccessIdentity id) {
while(url!=null){
if(map.containsKey(url)){
return map.get(url).validate(id);
}
url=UpUrl(url);
}
return false;
}

private String UpUrl(String url){
if(url==null)
return null;
if(url.contains("&")){
return url.split("&")[0];
}
if(url.contains("?"))
return url.split("\\?")[0];
if(url.contains("/")){
if("/".equals(url))
return null;
String t=url.substring(0,url.lastIndexOf("/"));
if(t.length()==0)
return "/";
return t;
}
return null;
}

public static AccessAnalyst getInstance() {
if (instance == null) {
synchronized (AccessAnalyst.class) {
if (instance == null) {
instance = new AccessAnalyst();
}
}
}
return instance;
}

public static void init() {
Config config=ConfigManager.getConfig("wzz.eu.jk.Access");
String base=ConfigManager.getEnviroment("ContextRoot");
try {
filepath = base+config.getValue("path");
} catch (ConfigMissingException e) {
System.err.println("Error: AccessAnalyst init config" +
" missing parameters "+e.getMessage());
}
}

private AccessAnalyst() {
map = new HashMap<String, Access>();
init();
readFile();
}

private void readFile() {
FileMan fm = new FileMan(filepath);
List<String> lines = fm.readLines();
fm.close();
String line;
String path;
Access access;
String[] g;
String[] gs;
for (int i = 0; i < lines.size(); i++) {
line = lines.get(i);
if(line.startsWith("#"))
continue;
gs = line.split(":");
path = gs[0];
access = new Access(path);
gs = gs[1].split("\\|");
for(int j=0;j<gs.length;j++){
g=gs[j].split(",");
for(int k=0;k<g.length;k++){
access.addPrivilege(g[k], j);
System.out.println(g[k]+" added to "+path);
}
}
map.put(path, access);
}
}
}


过滤器
public void doFilter(ServletRequest request, ServletResponse response,			FilterChain chain) throws IOException, ServletException {		HttpServletRequest r = (HttpServletRequest) request;		AccessIdentity id = (AccessIdentity) r.getSession().getAttribute("AccessIdentity");		if (id == null) {			id = new AccessIdentity(new ClientAnalyst(r).getIpAddr());			r.getSession().setAttribute("AccessIdentity", id);		}		id.notifyActive();		String query = r.getQueryString();		String url =r.getRequestURI().replace(r.getContextPath(), "")				+ ((query != null && query.length() > 0) ? ("?" + query) : "");		AccessAnalyst aa = AccessAnalyst.getInstance();		if(aa.check(url, id)){			chain.doFilter(request, response);			if(response instanceof HttpServletResponse)				((HttpServletResponse)response).setHeader("PowerBy", "WZZ.EvolutionUnit.JavaKit");		}		else{			if(response instanceof HttpServletResponse)				((HttpServletResponse)response).setStatus(404);		}	}