权限控制和session验证的实现

最近项目(struts2+spring+mybatis)中做了一个权限控制,做个简单的介绍:

基本思路是:在struts2中做一个拦截器,对所有action进行拦截,去判断用户是否有执行该action的权限,有则执行action,无责跳转到权限error页面;当然了,如何判断是否有权限,有很多实现方式,这里我们是写了一个listener,在web容器启动时会去读取一个配置了所有action的权限id的property文件,那么在拦截器拦截到action时就可以用这个信息来判断当前用户是否有权限执行该action。session的验证就更简单了,只要一个拦截器就行,不需要listener。

首先是在struts.xml中配置拦截器:

<!-- 全局配置:拦截器和错误跳转 -->
<package name="global" extends="struts-default">
<result-types>
<result-type name="json" class="org.apache.struts2.json.JSONResult" />
</result-types>

<interceptors>
<!-- セッションインターセプター -->
<interceptor name="sessionCheckInterceptor"
class="jp.com.interceptor.SessionCheckInterceptor" />

<!-- ユーザ権限インターセプター -->
<interceptor name="authCheckInterceptor"
class="jp.com.interceptor.AuthCheckInterceptor" />

<!-- 基本的なスタック -->
<interceptor-stack name="basicStack">
<interceptor-ref name="sessionCheckInterceptor" />
<interceptor-ref name="authCheckInterceptor" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>

</interceptors>

<default-interceptor-ref name="basicStack" />

<global-results>
<!-- リダイレクト -->
<result name="login" type="redirect">
<param name="location">/web/auth/login.jsp</param>
<param name="loginRedirectUrl">${loginRedirectUrl}</param>
</result>
<!-- リダイレクト -->
<result name="redirect" type="redirectAction">
<param name="actionName">redirect</param>
<param name="namespace">/common</param>
<param name="redirectUrl">${redirectUrl}</param>
</result>
<!-- サーバメンテナンスエラー -->
<result name="maintenance">/web/error/99001.jsp</result>

<!-- システムエラー -->
<result name="systemerror">/web/error/99002.jsp</result>

<!-- セッション切れエラー -->
<result name="sessiontimout">/web/error/99003.jsp</result>

<!-- 二重送信エラー -->
<result name="invalid.token">/web/error/99004.jsp</result>

<!-- アカウントに権限が付与されない場合、ダイアログを表示される。 -->
<result name="noPermit">/web/error/99005.jsp</result>
</global-results>

</package>

再来看下拦截器的实现类:

public class AuthCheckInterceptor extends MethodFilterInterceptor {

/** log */
private static Log log = LogFactory.getLog( AuthCheckInterceptor.class );

@SuppressWarnings("unchecked")
@Override
protected String doIntercept( ActionInvocation invocation ) throws Exception {
log.info( "AuthCheckInterceptor start" );
String interceptResult = null;

HttpSession httpSession = ServletActionContext.getRequest().getSession();

// 获取action动作机能id
String namespace = invocation.getProxy().getNamespace();
String actionname = invocation.getProxy().getActionName();
List<Integer> permisionLst = (List<Integer>) httpSession.getAttribute( "permision" );
String propKey = "";

if ( namespace != null ) {
// 去除namespace中的'/'
for ( int i = 0; i < namespace.length() && namespace.contains( "/" ); i++ ) {
if ( namespace.charAt( i ) == '/' ) {
namespace = namespace.substring( 0, i ) + namespace.substring( i + 1, namespace.length() );
}
}
propKey = namespace.toLowerCase() + ".";
}

propKey += actionname.toLowerCase();

Integer kinouId = KinouIdConsts.kinouID.get( propKey );

// 机能id存在,且机能id为-1(或用户权限包含该机能id),则进入机能
if ( ( kinouId != null && kinouId == -1 ) || ( permisionLst != null && permisionLst.contains( kinouId ) ) ) {
interceptResult = invocation.invoke();
}
// 无权限,则跳转无权限页面
else {
interceptResult = "noPermit";
}

log.info( "AuthCheckInterceptor end" );
return interceptResult;
}
}

这样一来,所有action在执行前都会执行该拦截器,而在拦截器的实现类中判断当前用户是否有权限时,用到了这样一个hashmap:
Integer kinouId = KinouIdConsts.kinouID.get( propKey );

它是从哪里来的呢?这里就用到了Listener。
首先在web.xml中配置监听器:

<listener>
<listener-class>jp.com.listener.PropertyLoaderListener</listener-class>
</listener>

之后当然是该监听器的实现类了:

public class PropertyLoaderListener implements ServletContextListener {

@Override
public void contextDestroyed( ServletContextEvent arg0 ) {
// TODO Auto-generated method stub
}

@Override
public void contextInitialized( ServletContextEvent arg0 ) {
// プロパティファイルを読み込む
String path = "WEB-INF/conf/common.properties";
String filePath = arg0.getServletContext().getRealPath( path );

FileInputStream inputFile;
try {
Properties prop = new Properties();
inputFile = new FileInputStream( filePath );
InputStreamReader reader = new InputStreamReader( inputFile );
prop.load( reader );

// 遍历 Properties
Iterator it = prop.entrySet().iterator();
while ( it.hasNext() ) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
Integer value = Integer.parseInt( (String) entry.getValue() );
KinouIdConsts.kinouID.put( key.toLowerCase(), value );
}

}
catch ( Exception e ) {
e.printStackTrace();
}
}

}

注意到这里是读取common.properties,这个文件很简单:

#权限机能配置
#格式:namespace.action=值
# [-1]:不進行權限驗證 [其他值]:進行權限驗證
# (未配入的值一律当"无权限"处理)
mainmenu.mainmenu=-1
opemgr.opemgrmenu=9
...

这样就搞定了,最后补充一下session拦截器的实现类:

public class SessionCheckInterceptor extends MethodFilterInterceptor {
/** log */
private static Log log = LogFactory.getLog(SessionCheckInterceptor.class);

@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
log.info("doIntercept start");
//如果是登录使用的action,用户退出的action,直接强制不进行session过期的验证
if(LoginAction.class == invocation.getAction().getClass()
|| LogoutAction.class == invocation.getAction().getClass())
{
return invocation.invoke();
}
//其他的所有的action都要使用判断session是否过期的拦截器站
// Get operator id from session
OperatorVO opeObj = (OperatorVO) invocation.getInvocationContext()
.getSession().get("ope_obj");
if (null == opeObj) {
return "sessiontimout";
}
log.info("doIntercept end");

return invocation.invoke();
}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值