关闭

[笔记-架构探险]框架优化与功能扩展3.2.安全框架shiro、提供安全控制特性2-jsp页面标签和框架aop启用权限控制

标签: 框架安全扩展shirotag
425人阅读 评论(0) 收藏 举报
分类:

http://git.oschina.net/zhuqiang/smart-framework 跟着书上学习的 框架git地址
http://git.oschina.net/zhuqiang/mrweb 依赖上面框架的demo练习
https://git.oschina.net/zhuqiang/smart-plugin-security.git 本章所学习的插件形式的shiro框架封装


jsp页面标签扩展和重定义shiro的标签

  1. 重定义 : 就是我们自己写tag,里面把shiro已经提供好的标签委托进来,意义在于,在jsp页面只需要导入我们框架的tag标签就行了。
  2. 扩展 : 利用shiro已经提供的标签进行继承 加以我们自己的逻辑进行扩展。

security.tld

编写我们自己的tag标签库文件,想要在页面上使用,就得把该tld文件放到(META-INF) META-INF/security.tld

<?xml version="1.0" encoding="ISO-8859-1"?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
        version="2.1">

    <tlib-version>1.0</tlib-version>
    <short-name>security</short-name>
    <uri>/security</uri>

    <!-- Invoke 'Generate' action to add tags or functions -->
    <tag>
        <description>对shiro的标签进行重定义(改变成自己的名字么?),判断当前用户是否已登录(包括:已认证与已记住)</description>
        <name>user</name>
        <tag-class>org.apache.shiro.web.tags.UserTag</tag-class>
        <body-content>JSP</body-content>
    </tag>
    <tag>
        <description>判断当前用户是否未登录(包括:未认证或未记住,即“访客”身份)</description>
        <name>guest</name>
        <tag-class>org.apache.shiro.web.tags.GuestTag</tag-class>
        <body-content>JSP</body-content>
    </tag>
    <tag>
        <description>判断当前用户是否拥有其中所有的角色(逗号分割,表示“与”的关系)</description>
        <name>hasAllRoles</name>
        <tag-class>cn.mrcode.smartPluginSecurity.tag.HasAllRoles</tag-class>
        <body-content>JSP</body-content>
        <attribute>
            <name>name</name> <!-- 这里的attr name 是HasAllRoles类中的属性名称哦。从RoleTag中继承来的-->
            <required>true</required>
            <rtexprvalue>true</rtexprvalue> <!-- 表示是否可以使用JSP表达式. -->
        </attribute>
    </tag>
</taglib>

扩展标签

import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.tags.RoleTag;

import java.util.Arrays;

/**
 * 判断当前用户是否拥有其中所有的角色(逗号分割,表示“与”的关系)
 * @author zhuqiang
 * @version V1.0
 * @date 2015/11/21 15:45
 */
public class HasAllRoles extends RoleTag {
    private static final String ROLE_NAMES_DELIMITER = ",";
    @Override
    protected boolean showTagBody(String roleName) {
        boolean hasAllRole = false;
        Subject subject = getSubject();
        if(subject != null){  //使用当前用户的 subject来获取授权的信息
            hasAllRole = subject.hasAllRoles(Arrays.asList(roleName.split(ROLE_NAMES_DELIMITER)));
        }
        return hasAllRole;
    }
}

* 页面使用 *

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%><!-  shiro的库,这里也引入了,是因为没有时间去重新定义更多的tag。而这个页面还用到了shiro的tag-->
<%@ taglib prefix="security" uri="/security" %> <!-  我们自己的tag库-->
<html>
<head>
    <title>首页</title>
</head>
<body>
<security:guest> <!-- 自己重定义的shiro的标签 -->
    <p>身份:游客</p>
    <a href="<c:url value='/login' />">登录</a>
    <a href="<c:url value='/register' />">注册</a>
</security:guest>

<security:user>
    <p>身份:<shiro:principal/></p>
    <a href="<c:url value='/customer' />">查询客户列表</a>
    <a href="<c:url value='/logout' />">退出</a>
</security:user>

<security:hasAllRoles name="sys"> <!-- 自己扩展的标签 -->
    有sys权限
</security:hasAllRoles>

</body>
</html>

aop启用权限控制,自定义注解实现授权特性

我们也可以使用aop来判断我们自定义的注解类型,进行拦截,不过。这本书挖了一个大坑。没有将怎么添加对插件切面的添加。问题是:

框架没有依赖插件,在现有的框架添加支持的时候,需要在aopHelper中关联 切面类所增强的目标类。
但是框架中获取不到AuthzAnnotationAspect的信息,就没法进行操作。真不知道是怎么关联上的。下面的代码是正确的思路,就是缺少怎么让框架 对 插件的aop支持。

/**
 * 判断当前用户是否未登录(包括:未认证或未记住)
 * @author zhuqiang
 * @version V1.0
 * @date 2015/11/21 16:40
 */
@Target({ElementType.TYPE,ElementType.METHOD}) //作用类和方法
@Retention(RetentionPolicy.RUNTIME)
public @interface User {
}
/**
 * 授权注解切面
 * @author zhuqiang
 * @version V1.0
 * @date 2015/11/21 16:43
 */
@Aspect(Controller.class) //对controller注解的类进行拦截增强
public class AuthzAnnotationAspect extends AspectProxy {
    // 定义基于授权功能的注解类数组
    private static final Class[] ANNOTATION_CLASS_ARRAY = {
        User.class
    };
    @Override
    public void before(Class<?> cls, Method method, Object[] params) throws Throwable {
        Annotation annotation = getAnnotation(cls, method);
        if(annotation != null){
            Class<? extends Annotation> annotationType = annotation.annotationType();
            if(annotationType.equals(User.class)){
                handleUser();
            }
        }
        super.before(cls, method, params);
    }

    /**
     * 从目标方法中获取相应的注解
     * @param cls
     * @param method
     * @return
     */
    private Annotation getAnnotation(Class<?> cls, Method method){
        // 不过这个处理,我在担心,如果这个方法上有多个注解的话,是否就包含更复杂的判断规则了,比如组合同时存在某种角色?
        for (Class annotationClass : ANNOTATION_CLASS_ARRAY) {
            // 目标方法是否带有授权注解
            if(method.isAnnotationPresent(annotationClass)){
                return method.getAnnotation(annotationClass);
            }
            //目标类上是否带有授权注解
            if(cls.isAnnotationPresent(annotationClass)){
                return cls.getAnnotation(annotationClass);
            }
        }
        return null; //都没有则返回空
    }

    private void handleUser() {
        Subject subject = SecurityUtils.getSubject();
        PrincipalCollection principals = subject.getPrincipals(); //还是利用shiro框架提供的功能来判断用户是否登录
        if(principals == null || principals.isEmpty()){
            throw new AuthzException("当前用户未登录");
        }
    }
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:113702次
    • 积分:1926
    • 等级:
    • 排名:千里之外
    • 原创:81篇
    • 转载:27篇
    • 译文:0篇
    • 评论:41条
    关于博客
    • 本博客记录一些学习笔记和工作开发中遇到的一些问题
    • QQ:99299684
    相关博客和项目
    1. mrcode 博客
    2016.02-2016.10为了学习技术而写的一个多人使用的博客
    2. 微信SDK自用封装
    工作中封装了一部分用到的微信api,搭成了一个架子,扩展方便。
    3. GitBook
    最近发现Gitbook能更好的记录笔记,以后就转移到这里了
    4. GitBook 自开发插件
    在使用GitBook过程中,方便使用,模仿开发了一些插件。
    最新评论