jeecms 前台拦截器的研究与改造
jeecms出发点是面向大众的,具有前台开发性,也就是说,即时是未登录(游客),也可以浏览到前台页面的内容,只是有些操作需要(增删改)注册和登录之后才可以进行。
后台当然不能随便进入了,必须登录后才可以进入后台,那么jeecms是怎么做的呢?我们看一看源码。
后台拦截器代码:
-
-
public boolean preHandle(HttpServletRequest request,
-
HttpServletResponse response, Object handler) throws Exception {
-
// 获得站点
-
CmsSite site = getSite(request, response);
-
CmsUtils.setSite(request, site);
-
// Site加入线程变量
-
CmsThreadVariable.setSite(site);
-
-
// 获得用户
-
CmsUser user = null;
-
if (adminId != null) {
-
// 指定管理员(开发状态)
-
user = cmsUserMng.findById(adminId);
-
if (user == null) {
-
throw new IllegalStateException("User ID=" + adminId
-
+ " not found!");
-
}
-
} else {
-
// 正常状态
-
Integer userId = authMng
-
.retrieveUserIdFromSession(session, request);
-
if (userId != null) {
-
user = cmsUserMng.findById(userId);
-
}
-
}
-
// 此时用户可以为null
-
CmsUtils.setUser(request, user);
-
// User加入线程变量
-
CmsThreadVariable.setUser(user);
-
//用户校验开始
-
String uri = getURI(request);
-
// 不在验证的范围内
-
if (exclude(uri)) {
-
return true;
-
}
-
// 用户为null跳转到登陆页面
-
if (user == null) {
-
response.sendRedirect(getLoginUrl(request));
-
return false;
-
}
-
//未登录用户重定向,用户校验结束
-
// 用户不是管理员,提示无权限。
-
if (!user.getAdmin()) {
-
request.setAttribute(MESSAGE, MessageResolver.getMessage(request,
-
"login.notAdmin"));
-
response.sendError(HttpServletResponse.SC_FORBIDDEN);
-
return false;
-
}
-
// 不属于该站点的管理员,提示无权限。
-
if (!user.getSites().contains(site)) {
-
request.setAttribute(MESSAGE, MessageResolver.getMessage(request,
-
"login.notInSite"));
-
response.sendError(HttpServletResponse.SC_FORBIDDEN);
-
return false;
-
}
-
boolean viewonly = user.getViewonlyAdmin();
-
// 没有访问权限,提示无权限。
-
if (auth && !user.isSuper()
-
&& !permistionPass(uri, user.getPerms(), viewonly)) {
-
request.setAttribute(MESSAGE, MessageResolver.getMessage(request,
-
"login.notPermission"));
-
response.sendError(HttpServletResponse.SC_FORBIDDEN);
-
return false;
-
}
-
return true;
-
}
1,获取请求uri并作处理,检测该uri是否符合要求,若不符合抛出异常。
2,如果当前请求的uri是例外的,放行,不做拦截,这里主要是对登录和登出的uri放行,防止死循环。
3,如果当前请求没有登录用户,则重定向到登录页。
具体的参数信息可以查看配置文件:jeecms-servlet-admin.xml
-
<bean id="adminContextInterceptor" class="com.jeecms.cms.web.AdminContextInterceptor">
-
<property name="auth" value="true"/>
-
<property name="loginUrl" value="/jeeadmin/jeecms/login.do"/>
-
<property name="returnUrl" value="/jeeadmin/jeecms/index.do"/>
-
<property name="excludeUrls">
-
<list>
-
<value>/login.do</value>
-
<value>/logout.do</value>
-
</list>
-
</property>
-
</bean>
整个重定向功能就是这样,那么我们前台也想要这种效果,不登陆用户不可以浏览任何页面,并定向到登陆页让其登录去,怎么办呢?
很简单了,比葫芦画瓢就是了。
首先我们找到前台url的拦截器:FrontContextInterceptor.java
-
public boolean preHandle(HttpServletRequest request,
-
HttpServletResponse response, Object handler)
-
throws ServletException {
-
CmsSite site = null;
-
List<CmsSite> list = cmsSiteMng.getListFromCache();
-
int size = list.size();
-
if (size == 0) {
-
throw new RuntimeException("no site record in database!");
-
} else if (size == 1) {
-
site = list.get(0);
-
} else {
-
String server = request.getServerName();
-
String alias, redirect;
-
for (CmsSite s : list) {
-
// 检查域名
-
if (s.getDomain().equals(server)) {
-
site = s;
-
break;
-
}
-
// 检查域名别名
-
alias = s.getDomainAlias();
-
if (!StringUtils.isBlank(alias)) {
-
for (String a : StringUtils.split(alias, ',')) {
-
if (a.equals(server)) {
-
site = s;
-
break;
-
}
-
}
-
}
-
// 检查重定向
-
redirect = s.getDomainRedirect();
-
if (!StringUtils.isBlank(redirect)) {
-
for (String r : StringUtils.split(redirect, ',')) {
-
if (r.equals(server)) {
-
try {
-
response.sendRedirect(s.getUrl());
-
} catch (IOException e) {
-
throw new RuntimeException(e);
-
}
-
return false;
-
}
-
}
-
}
-
}
-
if (site == null) {
-
throw new SiteNotFoundException(server);
-
}
-
}
-
-
CmsUtils.setSite(request, site);
-
-
CmsUser user = null;
-
Integer userId = authMng.retrieveUserIdFromSession(session, request);
-
if (userId != null) {
-
user = cmsUserMng.findById(userId);
-
}
-
-
if (user != null) {
-
CmsUtils.setUser(request, user);
-
}
-
return true;
-
}
拦截器很简单,并没有在检测到用户无效后做任何措施,不管怎样都是放行的,那么我们就在最后一个if路面添加else,也就是说if(user==null)我们就做些事情:
其配置文件jeecms-servlet-front.xml并没有对该拦截器配置参数,那么我们就自己来配置,当然要仿照后台的拦截器来配:
-
<bean id="frontContextInterceptor" class="com.jeecms.cms.web.FrontContextInterceptor">
-
<property name="loginUrl" value="/login.jspx"/>
-
<property name="returnUrl" value="/tjhq"/>
-
<property name="excludeUrls">
-
<list>
-
<value>/login.jspx</value>
-
<value>/logout.jspx</value>
-
</list>
-
</property>
-
</bean>
loginUrl是登录页的url,returnUrl指的是登陆后进入的url,而excludeUrls是例外情况,也就是说碰到这两个url都放行。
最后一个if改为:
-
if (user != null) {
-
CmsUtils.setUser(request, user);
-
}else{
-
String uri = getURI(request);
-
// 不在验证的范围内
-
if (exclude(uri)) {
-
return true;
-
}
-
// 用户为null跳转到登陆页面
-
if (user == null) {
-
try {
-
response.sendRedirect(getLoginUrl(request));
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
return false;
-
}
-
}
这样,我们的前台页面也跟后台一致了,都实现了登录重定向功能。