1. 程式人生 > >如何自定義註解實現簡單的許可權控制

如何自定義註解實現簡單的許可權控制

為什麼需要許可權控制?

當一個系統建成之後,需要適當的做一些許可權控制,使得某些非法使用者不能隨意更改系統,而允許某些特權使用者可以作業系統.

一般系統如何實現許可權控制?

一般系統如果許可權較為複雜,可能需要藉助一些許可權控制框架,例如shiro來實現許可權控制,但是shiro過於重,有些系統許可權控制較為簡單,使用shiro有些殺雞焉用牛刀了;一些公司的業務較多,但是許可權主體相同,這種場景下,一般我們會將許可權系統剝離處理,做成介面形式,統一管理各個業務之間的許可權形式.

如何實現簡單的許可權控制?

一般的專案中都需要做一些簡單的登入控制,比如有些操作需要特定的使用者才能訪問,而有些操作則不需要.

一般專案中我們會採用過濾器實現攔截過濾某些方法的功能,可根據攔截方法和放行的方法的比例來實現功能,
當和spring結合使用時,我們既可以使用過濾其實現,也可以通過繼承HandlerInterceptorAdapter,來利用aop實現攔截方法

但是使用以上方法時,我們不能靈活控制權限更改問題,每次當權限變動都需要改動程式碼,業務侵入性高,而且不利於理解,
其實我們可以參考shiro的註解實現,編寫一些特定的註解實現許可權控制.

自定義註解實現方法攔截

本篇文章只是簡單講解下,方法攔截,做一些簡單的許可權控制,不做複雜的,
一些稍微複雜的許可權控制,例如讀取資料庫中的許可權資訊,可以根據業務在許可權攔截器中實現.

程式碼實戰

許可權註解:

package com.taoyuan.ebook.anno;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.web.bind.annotation.Mapping;

/**
 * @author
都市桃源 *許可權自定義註解 簡版,可以註解在方法和類上 */
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface Interception { //是否允許 boolean permit() default false; }

攔截器實現程式碼

package com.taoyuan.ebook.anno;

import java.io.IOException;
import java.util.Arrays;

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

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

import com.taoyuan.ebook.util.CookieUtil;
import com.taoyuan.ebook.util.PropertiesUtil;

public class PermissionInterceptor extends HandlerInterceptorAdapter {

    public static final String LOGIN_TOKEN;
    static {
        LOGIN_TOKEN= PropertiesUtil.getString("LOGIN_TOKEN");
    }

    public static boolean login(HttpServletResponse response, boolean ifRemember){
        CookieUtil.set(response, LOGIN_TOKEN, ifRemember);
        return true;
    }
    public static void logout(HttpServletRequest request, HttpServletResponse response){
        CookieUtil.remove(request, response, LOGIN_TOKEN);
    }
    public static boolean ifLogin(HttpServletRequest request){
        String info= CookieUtil.getValue(request, LOGIN_TOKEN);
        if (info==null || !LOGIN_IDENTITY_TOKEN.equals(info.trim())) {
            return false;
        }
        return true;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (!(handler instanceof HandlerMethod)) {
            return super.preHandle(request, response, handler);
        }

        if (!ifLogin(request)) {
            HandlerMethod method = (HandlerMethod)handler;
            //獲取方法上的註解
            Interception methodPermission = method.getMethodAnnotation(Interception.class);
            Interception typePermission=method.getBeanType().getAnnotation(Interception.class);
            if (methodPermission!=null) {//檢測註解
                if(methodPermission.permit()){
                    return true;
                }else{//優先檢測方法註解,攔截
                    return handle(request, response);
                }

            }
            if (typePermission!=null) {//檢測類註解
                boolean permit = typePermission.permit();
                if(typePermission.permit()){
                    return true;
                }else{//優先檢測方法註解,攔截
                    return handle(request, response);
                }
            }
        }

        return super.preHandle(request, response, handler);
    }

    public boolean handle(HttpServletRequest request, HttpServletResponse response) throws IOException{
        response.sendRedirect(request.getContextPath() + "/toLogin");
        return false;
    }

}

使用

@Controller
@RequestMapping("/book")
@Interception
//註解類上,表示全部攔截@Interception
//@Interception(permit=true) 表示全部放行
public class BookControler {
    @Autowired
    BookService bookService;

//也可以註解方法上
    @Interception(permit=true)
    @RequestMapping("/getAll")
    public  @ResponseBody List<Book> getAll() throws Exception{
        return bookService.selectAll();

    }


}

然後將攔截器配置一下就好