您的位置:首页 > 编程语言 > Java开发

基于注解和拦截器的权限控制

2015-12-15 17:21 465 查看
        互联网中各种各样的系统非常多,但是始终都离不开权限控制。一个好的权限控制对系统的安全性有着极大的提升,最近写了一个简单实用的权限验证的小例子,在这里分享下我的想法。

        我们使用注解+拦截器来实现权限控制,以注解来标示某个类或者方法的权限,用拦截器来验证用户的权限,把权限控制细化到了每个方法。

所需材料:

    注解:PrivCtrl

    控制器:UserController

    Bean:User,Request

    枚举:PrivCtrlType

    工具:RequestFactory,HttpClientUtil,SessionUtil

    拦截器:PrivCtrlInterceptor

首先我们需要一个枚举类来保存我们系统所拥有的各种权限类型:

package com.liyh.enumeration;

public enum PrivCtrlType {
/** 游客 */
PUBLIC(0),
/** 会员 */
MEMBER(1);

private int code;

private PrivCtrlType(int code) {
this.code = code;
}

@Override
public String toString() {
return String.valueOf(code);
}
}

紧接着我们需要定义一个注解用来标示类和方法的权限:

package com.liyh.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import com.liyh.enumeration.PrivCtrlType;

@Retention(RetentionPolicy.RUNTIME)
public @interface PrivCtrl {
PrivCtrlType[] value() default {PrivCtrlType.PUBLIC};
}


使用一个用户对象来记录用户信息,一个Session工具来操作当前会话的用户以及其他信息:

package com.liyh.domain;

import com.liyh.enumeration.PrivCtrlType;

public class User {

private String id;
private String username;
private String password;
private String type = PrivCtrlType.MEMBER.toString();

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

}
package com.liyh.utils;

import java.util.Date;

import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import com.liyh.domain.User;

public class SessionUtil {

private static final String KEY_USER = "User";
private static final String KEY_LOGIN_TIME = "loginTime";

public static void invalid() {
RequestAttributes requestAttributes =  RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
requestAttributes.removeAttribute(KEY_USER, RequestAttributes.SCOPE_SESSION);
requestAttributes.removeAttribute(KEY_LOGIN_TIME, RequestAttributes.SCOPE_SESSION);
}
}

public static void login(User user) {
RequestAttributes requestAttributes =  RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
requestAttributes.setAttribute(KEY_USER, user, RequestAttributes.SCOPE_SESSION);
requestAttributes.setAttribute(KEY_LOGIN_TIME, new Date(), RequestAttributes.SCOPE_SESSION);
}
}

public static User getCurrentUser() {
User user = null;
RequestAttributes requestAttributes =  RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
user = (User)requestAttributes.getAttribute(KEY_USER, RequestAttributes.SCOPE_SESSION);
}
return user;
}

public static String getUserId() {
User user = getCurrentUser();
if (user != null) {
return user.getId();
}
return null;
}

public static Date getlastLoginTime() {
Date lastLoginTime = null;
RequestAttributes requestAttributes =  RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
lastLoginTime = (Date) requestAttributes.getAttribute(KEY_LOGIN_TIME, RequestAttributes.SCOPE_SESSION);
}
return lastLoginTime;
}
}


还需要一个对象来记录请求信息,一个工厂来实例化一个请求信息:

package com.liyh.domain.utils;

import java.util.Map;

/* 请求参数 */
public class Request {

private boolean send;

private String url;

private String method;

private Map<String, String[]> parameterMap;

public boolean isSend() {
return send;
}

public void setSend(boolean send) {
this.send = send;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getMethod() {
return method;
}

public void setMethod(String method) {
this.method = method;
}

public Map<String, String[]> getParameterMap() {
return parameterMap;
}

public void setParameterMap(Map<String, String[]> parameterMap) {
this.parameterMap = parameterMap;
}

}
package com.liyh.factory;

import javax.servlet.http.HttpServletRequest;

import com.liyh.domain.utils.Request;

public class RequestFactory {

public static Request createReuqest(HttpServletRequest request) {
Request myRequest = new Request();
myRequest.setUrl(request.getRequestURL().toString());
myRequest.setMethod(request.getMethod());
myRequest.setParameterMap(request.getParameterMap());
return myRequest;
}
}


我们首先通过拦截器验证当前用户是否有请求权限:

package com.liyh.interceptor;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.liyh.annotation.PrivCtrl;
import com.liyh.domain.User;
import com.liyh.enumeration.PrivCtrlType;
import com.liyh.factory.RequestFactory;
import com.liyh.utils.SessionUtil;

/** 权限拦截器 */
public class PrivCtrlInterceptor extends HandlerInterceptorAdapter {

@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
PrivCtrl privCtrl = getPrivCtrl((HandlerMethod) handler);
if (isLoginRequired(privCtrl) && !verifyPrivCtrl(privCtrl)) {
loginRedirect(request, response);
}
return true;
}

/** 获取权限注解 */
private PrivCtrl getPrivCtrl(HandlerMethod method) {
PrivCtrl ctrlAnnnotation = method.getMethodAnnotation(PrivCtrl.class);
if (ctrlAnnnotation == null) {
ctrlAnnnotation = method.getBeanType().getAnnotation(PrivCtrl.class);
}
return ctrlAnnnotation;
}

/** 判断是否需要登录 */
private boolean isLoginRequired(PrivCtrl privCtrl) {
if (privCtrl == null) {
return false;
}
for (PrivCtrlType privCtrlType : privCtrl.value()) {
if (privCtrlType != PrivCtrlType.PUBLIC) {
return true;
}
}
return false;
}

/** 权限验证 */
private boolean verifyPrivCtrl(PrivCtrl privCtrl) {
User user = SessionUtil.getCurrentUser();
if (user == null) {
return false;
}
for (PrivCtrlType privCtrlType : privCtrl.value()) {
if (privCtrlType.toString().equals(user.getType())) {
return true;
}
}
return false;
}

/** 登录重定向 */
private void loginRedirect(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.getSession().setAttribute("request", RequestFactory.createReuqest(request));
response.setStatus(302);
response.addHeader("Location", request.getContextPath() + "/user/login");
response.flushBuffer();
}
}


权限验证不通过时保存请求信息并跳转到登录页面进行登录:

package com.liyh.controller;

import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.liyh.annotation.PrivCtrl;
import com.liyh.domain.User;
import com.liyh.domain.utils.Request;
import com.liyh.enumeration.PrivCtrlType;
import com.liyh.service.UserService;
import com.liyh.utils.HttpClientUtil;
import com.liyh.utils.SessionUtil;
import com.liyh.utils.StringUtil;

@Controller
@RequestMapping("/user")
public class UserController {

@Resource
private UserService userService;

@RequestMapping(value="/login", method = RequestMethod.GET)
public ModelAndView login(Map<String, Object> model,
HttpServletRequest request) {
HttpSession session = request.getSession();
Request preRequest = (Request) session.getAttribute("request");
if (preRequest != null) {
if (preRequest.isSend()) {
session.removeAttribute("request");
} else {
preRequest.setSend(true);
}
}
return new ModelAndView("user/login");
}

@RequestMapping(value="/login", method = RequestMethod.POST)
public String login(String username, String password, Map<String, Object> model,
HttpServletRequest request, HttpServletResponse response) throws Exception{
User user = userService.findByUsername(username);
if (user == null || !StringUtil.equals(user.getPassword(), password)) {
model.put("rs", "fail");
model.put("msg", "登录失败");
model.put("username", username);
return "user/login";
}
SessionUtil.login(user);
HttpSession session = request.getSes
9802
sion();
Request preRequest = (Request) session.getAttribute("request");
if (preRequest != null) {
session.removeAttribute("request");
user = (User) session.getAttribute("User");
HttpClientUtil.send(response, preRequest);
return null;
}
return "redirect:/";
}

@PrivCtrl(PrivCtrlType.MEMBER)
@RequestMapping(value="/login_success", method = RequestMethod.GET)
public ModelAndView login_success(Map<String, Object> model, HttpServletRequest request) {
return new ModelAndView("user/login_success");
}

}


登录过后通过自制的Http客户端工具跳转到保存的请求页面:

package com.liyh.utils;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import com.liyh.domain.utils.Request;

public class HttpClientUtil {

public static void send(HttpServletResponse response, Request request) throws IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
out.println("<HTML>");
out.println(" <HEAD><TITLE>sender</TITLE></HEAD>");
out.println(" <BODY>");
out.println("<form name=\"submitForm\" action=\"" + request.getUrl() + "\" method=\"" + request.getMethod() +"\">");
Map<String, String[]> params = request.getParameterMap();
for (String key : params.keySet()) {
String[] values = params.get(key);
for (String value : values) {
out.println("<input type=\"hidden\" name=\"" + key + "\" value=\"" + value + "\"/>");
}
}
out.println("</from>");
out.println("<script>window.document.submitForm.submit();</script> ");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
}
}


总结:

        存在问题:Ajax请求的接口没有做额外处理,暂时还没有完善

        解决方案:拦截器中判断是否是请求接口,如果是请求接口,则返回权限不足,需要封装Ajax请求方法,未登录时跳转到登录页面并记录当前URL
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 权限