该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
干才有人问我要的.qq,不太喜欢加人.发这里吧.
说明:这个demo是单点登录一个思路,基于单机服务器的,全局globalsession 管理同样的思路,建议使用memcache或者redis,做一套session系统或者只维护session状态.
这个是基于内存map实现的,ps:说是demo,实际上是可以企业直接用的
url级别权限控制器.基于filter实现:
package com.an.core.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import com.an.core.exception.ForbiddenException;
import com.an.core.exception.UnauthorizedException;
import com.an.core.utils.PayLoadRequestWrapper;
import com.an.core.utils.Util;
import com.an.sys.entity.User;
/**
* 用户权限过滤器(用户身份及权限验证)
*
* @author Karas
* @date
*/
public class GrantedFilter extends HttpServlet implements Filter {
private FilterConfig config;
private static final long serialVersionUID = -4275105240038370264L;
private static Logger logger = Logger.getLogger(GrantedFilter.class);
public static final ThreadLocal threadLocal = new ThreadLocal<>();
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String uri = Util.nvl(request.getRequestURI(), "");
String method = request.getMethod();
String ip = request.getRemoteAddr();
String username = " ";
boolean flag = true;
String regEx = "(?<=" + request.getContextPath() + "/)[^/]+(/[^/]+|$)";
String act = "";
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(uri.replace("/rest/", "/"));
if (matcher.find())
act = matcher.group();
String exclude = config.getInitParameter("exclude");
if (act.isEmpty() || !exclude.contains(act)) { // 需验证区域
try {
HttpSession session = request.getSession();
if (session == null)
throw new UnauthorizedException();
if (!SessionIntercept.isAlive(session.getId())) {
session.invalidate();
throw new UnauthorizedException("你已被强制登出!");
}
User user = (User) session.getAttribute(User.SESSION_KEY);
if (user == null)
throw new UnauthorizedException();
username = user.getLoginName();
if (!act.isEmpty() && !user.granted(act, method)) // 验证用户所访问资源权限许可
throw new ForbiddenException();
threadLocal.set(user);
if (user.isFirstTime()){
response.setContentType("text/html;charset=utf-8");
RequestDispatcher rd = request
.getRequestDispatcher("/sys/firstTime.html");
rd.forward(servletRequest, servletResponse);
}
} catch (UnauthorizedException e) {
flag = false;
response.setStatus(401);
if ("XMLHttpRequest".equals(request
.getHeader("X-Requested-With"))) {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write("登录超时!");
out.flush();
out.close();
} else {
response.setContentType("text/html;charset=utf-8");
RequestDispatcher rd = request
.getRequestDispatcher("/login.html");
rd.forward(servletRequest, servletResponse);
}
} catch (ForbiddenException e) {
flag = false;
response.setStatus(403);
if ("XMLHttpRequest".equals(request
.getHeader("X-Requested-With"))) {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write("权限验证失败!");
out.flush();
out.close();
} else {
response.setContentType("text/html;charset=utf-8");
RequestDispatcher rd = request
.getRequestDispatcher("/login.html");
rd.forward(servletRequest, servletResponse);
}
} catch (Exception e) {
flag = false;
response.setStatus(503);
logger.error(e.getMessage(), e);
} finally {
StringBuffer sb = new StringBuffer("ip:" + ip);
sb.append(",");
sb.append(request.getMethod());
sb.append(",");
sb.append(response.getStatus());
sb.append(",u:");
sb.append(username);
sb.append(",:");
sb.append(uri);
sb.append(",body:");
if ("application/json".equalsIgnoreCase(request.getContentType())) {
PayLoadRequestWrapper wrapper = new PayLoadRequestWrapper(
request);
sb.append(wrapper.getBody());
request = wrapper;
} else {
sb.append(JSONObject.fromObject(request.getParameterMap())
.toString());
}
logger.info(sb);
}
}
if (flag) {
filterChain.doFilter(request, response);
}
}
public void destroy() {
this.config = null;
}
}
然后是session状态管理器,基于map实现,这个如果换成基于reids实现就可以应用到分布式系统,并且避免了session复制,同时,如果要使用restful风格的去session ,就要自己写一个系统,这里只提供思路
package com.an.core.controller;
import javax.servlet.http.HttpSession;
import java.util.*;
/**
* Session 状态管理
* Created by karas on 9/2/14.
*/
public class SessionIntercept {
private static Map AppSession = new HashMap<>();
public static void forceQuit(String userId) {
Set> set = AppSession.entrySet();
for (Map.Entry entry : set) {
if (userId.equals(entry.getValue())) {
AppSession.remove(entry.getKey());
}
}
AppSession.remove(userId);
}
public static void add(String userId, String sessionId) {
AppSession.put(sessionId, userId);
}
public static boolean isAlive(String value) {
return AppSession.containsKey(value);
}
public static boolean isOnline(String key) {
return AppSession.containsValue(key);
}
public static boolean isOnline(String userId, HttpSession session) {
Set> set = AppSession.entrySet();
for (Map.Entry entry : set) {
if (entry.getValue().equals(userId) && !session.getId().equals(entry.getKey())) {
return true;
}
}
return false;
}
public static void remove(String sid) {
AppSession.remove(sid);
}
}