10.5.3 处理前端权限控制

10.5.3 处理前端权限控制

在本系统中有些页面需要用户登录才能处理,因此系统会对这些页面进行权限检查。因此,本系统额外定义了一个控制器。该控制器检查HttpSession中是否包含用户登录ID,如果包含登录的用户ID,则表明用户已经登录,否则提示用户登录系统。下面是用于权限检查的控制器类。
程序清单:codes\10\auction\src\org\crazyit\auction\controller\authority\AuthController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package org.crazyit.auction.controller.authority;

import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/auction")
public class AuthController
{
@RequestMapping(value = "/authLogin")
@ResponseBody
public String preHandle(HttpSession session) throws Exception
{
// 1.在请求拦截执行之前 ,判断请求是否有权限
// 取出HttpSession里的userId属性
Integer userId = (Integer) session.getAttribute("userId");
// 如果HttpSession里的userId属性为null,或小于等于0
if (userId == null || userId <= 0)
{
// 如果还未登录,抛出异常
return "false";
} else
{
return "true";
}
}
}

接下来为了让该控制器返回结果,程序会在请求页面之前先向该控制器发送请求,只有判断用户登录之后才能继续请求目标页面。下面goPage()函数负责页面跳转功能,该函数判断被跳转页面是否需要进行权限检查,该函数的代码如下。
程序清单:codes\10\auction\WebContent\js\index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 定义一个方法用于处理菜单功能 
function goPage(pager) {
// 如果是需要被拦截的功能先做登录校验
if (pager == "viewSucc.html" || pager == "viewOwnerItem.html"
|| pager == "viewBid.html" || pager == "addItem.html"
|| pager == "addBid.html") {
$.post("auction/authLogin", {}, function(data) {
if (data != "true") {
$('#myModal').modal('show');
$("#tip").html(
"<span style='color:red;'>您还没有登录,请先登录再执行该操作</span>");
} else {
// 将pager装载到ID为data的元素中显示
$("#data").load(pager);
history.pushState(null, null, pager);
}
});
} else {
// 将pager装载到ID为data的元素中显示
$("#data").load(pager);
history.pushState(null, null, pager);
}
}

正如上面代码所示所示,只要程序访问列出的那些页面,系统将会先判断用户是否登录,如果用户并未登录则会提示用户需要登录
前面介绍的只是浏览器端JS的权限控制,此外还需要在前端控制器中执行权限检查。本系统考虑使用Around Advice来进行权限控制:Around Advice检查调用者的HttpSession状态,如果HttpSession包含了用户登录信息,就允许调用者调用前端处理方法;否则返回提示信息,提示用户登录。
提示:Around AdviceAOP编程中Advice的一种,关于Spring AOPAround Advice的内容,请参考”疯狂Java体系”的《轻量级Java EE企业应用实战》。
Around Advice类的代码如下。
程序清单:codes\10\auction\src\org\crazyit\auction\controller\authority\AuthorityInterceptor.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package org.crazyit.auction.controller.authority;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.ProceedingJoinPoint;

public class AuthorityInterceptor
{
// 进行权限检查的方法
public Object authority(ProceedingJoinPoint jp) throws Throwable
{
System.out.println("----------------------=====--------------------");
HttpSession sess = null;
// 获取被拦截方法的全部参数
Object[] args = jp.getArgs();
// 遍历被拦截方法的全部参数
for (int i = 0; i < args.length; i++)
{
// 找到HttpSession类型的参数
if (args[i] instanceof HttpSession)
sess = (HttpSession) args[i];
}
// 取出HttpSession里的userId属性
Integer userId = (Integer) sess.getAttribute("userId");
// 如果HttpSession里的userId属性为null,或小于等于0
if (userId == null || userId <= 0)
{
// 如果还未登录,抛出异常
Map<String, String> map = new HashMap<>();
map.put("error", "您还没有登录,必须先登录才能使用该功能");
return map;
}
return jp.proceed();
}
}

正如我们从上面代码所看到的,Around Advice 会检查浏览者的HttpSession 状态,如果HttpSession中的userIdnulluserId的值小于0,则系统返回一个Map对象,该对象包含了提示用户登录的信息。
定义了该Around Advice之后,还需要将它配置在SpringMVC控制器所在的容器中。
程序清单:codes\10\auction\WebContent\WEB-INF\springmvc-servlet.xml

粗体字代码指定在执行org.crazyit.auction.controller 包下任意类的系列方法之前,先调用authorityAspectauthority()方法,该方法用于进行权限控制:保证只有具有相应权限的浏览者才能调用前端处理方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- 定义一个普通Bean实例,该Bean实例将进行权限控制 -->
<bean
id="authority"
class="org.crazyit.auction.controller.authority.AuthorityInterceptor" />

<aop:config>
<!-- 将authority转换成切面Bean -->
<aop:aspect ref="authority">
<!-- 定义一个Before增强处理,直接指定切入点表达式 以切面Bean中的authority()方法作为增强处理方法 -->
<aop:around
pointcut="execution(* org.crazyit.auction.controller.*.getItemByWiner(..))
or execution(* org.crazyit.auction.controller.*.getBidByUser(..))
or execution(* org.crazyit.auction.controller.*.getItemsByOwner(..))
or execution(* org.crazyit.auction.controller.*.addItem(..))
or execution(* org.crazyit.auction.controller.*.addBid(..))"
method="authority" />
</aop:aspect>
</aop:config>