Shiro通过注解配置授权

接着上一篇文章的基础之上:

pom中添加一个切面编程aop的依赖:

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>    

然后在spring-mvc.xml文件中开启aop并做相关配置:

<!--//开启aop-->
    <aop:config proxy-target-class="true"/>
    <!--创建一个保证shiro内部Lifecycle正常执行的对象-->
    <bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <!--创建一个shiro授权生效的对象-->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

接着在controller中添加:

@RequiresRoles("admin")//这个注解的含义是:必须具备指定角色才可以访问这个链接,执行这个方法
    @RequestMapping(value = "/testRole",method = RequestMethod.GET)
    @ResponseBody
    public String testRole(){
        return "test Role success";
    }

    @RequiresRoles("admin1")//这个注解的含义是:必须具备指定角色才可以访问这个链接,执行这个方法
    @RequestMapping(value = "/testRole1",method = RequestMethod.GET)
    @ResponseBody
    public String testRole1(){
        return "test Role success";

然后运行:

先登录:

登录成功后访问url:

访问成功,说明具备角色。

接着访问另一个url:/testRole1

报错500,

Subject does not have role [admin1]

说明controller中的注解已经生效。

还有另一种注解:指定具有相应权限才可访问

@RequiresPermissions({"login","user:select"})//这个注解的含义是:必须具备指定权限才可以访问这个链接,执行这个方法
    @RequestMapping(value = "/testPermission",method = RequestMethod.GET)
    @ResponseBody
    public String testPermission(){
        return "test Permission success";
    }

这里在上一篇博客的基础之上,还需要修改一下自定义Realm中的授权内容与getPermissionsByUserName方法,修改后的内容如下:

@Component
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private UserDao userDao;

    //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //1.通过主体传过来的认证信息中去获取用户名
        String userName = (String) principalCollection.getPrimaryPrincipal();
        //实际开发时这里从数据库或者缓存中获取角色数据
        Set<String> roles = getRolesByUserName(userName);

        Set<String> permissions = getPermissionsByUserName(userName);
        //将取来的角色数据与权限数据返回
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        //设置权限
        simpleAuthorizationInfo.setStringPermissions(permissions);
        //设置角色
        simpleAuthorizationInfo.setRoles(roles);

        return simpleAuthorizationInfo;
    }

    /**
     * 根据用户名获取权限信息
     * @return
     */
    private Set<String> getPermissionsByUserName(String userName) {
        List<String> list = userDao.queryPermissionsByUserName(userName);
        Set<String> sets= new HashSet<>(list);
        return sets;
    }

    /**
     * 根据账号取角色信息
     * @param userName
     * @return
     */
    private Set<String> getRolesByUserName(String userName) {
        List<String> list = userDao.queryRolesByUserName(userName);
        Set<String> sets = new HashSet<>(list);
        return sets;
    }

    //认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        //1.通过主体传过来的认证信息中去获取用户名
        String userName = (String)authenticationToken.getPrincipal();

        //2.通过用户名到数据库中获取凭证
        String password = getPasswordByUserName(userName);
        if (password == null){
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo
                (userName,password,"customRealm");

        return authenticationInfo;
    }

    /**
     * 模拟数据库查询凭证
     * @param userName
     * @return
     */
    private String getPasswordByUserName(String userName){
        //查询数据库
        user user = userDao.getUserByUserName(userName);
        if (user != null){
            return user.getPassword();
        }
        return null;
    }

    public static void main(String[] args){
        //因为是模拟数据库操作,
        //数据库中的密码应该都是被MD5加密过的数据
        //所以需要在这里直接打印出加密后的密码
        Md5Hash md5Hash = new Md5Hash("123qwe");
        System.out.println(md5Hash.toString());
    }
}

这里在userDao中插入了queryPermissionsByUserName(userName);方法,代码如下:

@Override
    public List<String> queryPermissionsByUserName(String userName) {
        String sql = "select r.permission from roles_permissions r,user_roles u where u.role_name = r.role_name and u.username = ?";

        List<String> permissions = jdbcTemplate.query(sql, new String[]{userName}, new RowMapper<String>() {
            @Override
            public String mapRow(ResultSet resultSet, int i) throws SQLException {
                return resultSet.getString("permission");
            }
        });

        if (CollectionUtils.isEmpty(permissions)){

            return null;
        }else {
            for (String s : permissions) {
                System.out.println(s);
            }
            return permissions;
        }
    }

运行访问结果如下:

PS:这里一定要注意数据的设置与返回,也就自定义Realm中的:

     //实际开发时这里从数据库或者缓存中获取角色数据
        Set<String> roles = getRolesByUserName(userName);

        Set<String> permissions = getPermissionsByUserName(userName);
        //将取来的角色数据与权限数据返回
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        //设置权限
        simpleAuthorizationInfo.setStringPermissions(permissions);
        //设置角色
        simpleAuthorizationInfo.setRoles(roles);

        return simpleAuthorizationInfo;

这部分代码,之前因为马虎,

     //设置权限
        simpleAuthorizationInfo.setStringPermissions(permissions);忘记塞这个步骤中的permissions了,导致疯狂500错误:org.apache.shiro.authz.UnauthorizedException: Subject does not have permission

原文地址:https://www.cnblogs.com/xk920/p/10825706.html

时间: 2025-01-17 23:18:21

Shiro通过注解配置授权的相关文章

shiro+spring相关配置

一.在web.xml配制shiroFilter <!-- 配置Shiro过滤器,先让Shiro过滤系统接收到的请求 --> <!-- 这里filter-name必须对应applicationContext.xml中定义的<bean id="shiroFilter"/> --> <!-- 使用[/*]匹配所有请求,保证所有的可控请求都经过Shiro的过滤 --> <!-- 通常会将此filter-mapping放置到最前面(即其他fi

32、shiro框架入门3.授权

一. 授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等).在授权中需了解的几个关键对象:主体(Subject).资源(Resource).权限(Permission).角色(Role). 1. 主体 主体,即访问应用的用户,在Shiro中使用Subject代表该用户.用户只有授权后才允许访问相应的资源. 资源 在应用中用户可以访问的任何东西,比如访问JSP页面.查看/编辑某些数据.访问某个业务方法.打印文本等等都是资源.用户只要授权后才能访问. 权限 安全策略

springboot + shiro 权限注解、请求乱码解决、统一异常处理

springboot + shiro 权限注解.请求乱码解决.统一异常处理 前篇 后台权限管理系统 相关: spring boot + mybatis + layui + shiro后台权限管理系统 springboot + shiro之登录人数限制.登录判断重定向.session时间设置 springboot + shiro 动态更新用户信息 基于前篇,新增功能: 新增shiro权限注解: 请求乱码问题解决: 统一异常处理. 源码已集成到项目中: github源码: https://githu

微信JS SDK配置授权,实现分享接口

微信开放的JS-SDK面向网页开发者提供了基于微信内的网页开发工具包,最直接的好处就是我们可以使用微信分享.扫一扫.卡券.支付等微信特有的能力.7月份的时候,因为这个分享的证书获取问题深深的栽了一坑,后面看到"config:ok"的时候真的算是石头落地,瞬间感觉世界很美好.. 这篇文章是微信开发的很多前置条件,包括了服务端基于JAVA的获取和缓存全局的access_token,获取和缓存全局的jsapi_ticket,以及前端配置授权组件封装,调用分享组件封装. 配置授权思路:首先根据

基于javaConfig和注解配置Spring Security

Spring Security 借助一系列Servlet Filter 来提供安全性功能,但是借助Spring的小技巧,我们只需要配置一个Filer就可以了,DelegatingFilterProxy是一个特殊的Servlet Filter,它本身所做的工作并不多,只是将工作委托给一个javax.servlet.Filter 的实现类,这个实现类作为一个bean注册再Spring应用的上下文中. 如果了解过用xml配置spring security的朋友就知道,用基于xml配置Spring Se

shiro整合spring配置

shiro应用到项目中,一般都是通过spring来管理.下面就如何把shiro整理到spring中进行了讲解,及给出了配置的步骤: 一.pom.xml文件配置 本例子主要是介绍maven管理的web项目进行配置介绍,因此,首先需建立好一个maven管理的web项目(可参考本博客创建maven管理的web项目). pom.xml文件配置,主要是添加相关依赖的jar支持.因为整合到spring中需添加spring支持.具体配置参考配置代码: 1 <project xmlns="http://m

Spring+Shiro+CAS整合配置笔记

一.前言 Apache Shiro与Spring Security一样是Java的一个安全框架.那为什么与Spring整合却用Shiro?不要问为什么,任性!开个玩笑:D 其实我个人是认为Spring Security太过于笨重,要写太多的过滤器.我是个怕麻烦的人,Shiro的配置简单这就是我选择的理由,何况Spring官方自己都推荐使用Shiro.而Shiro权限控制与CAS单点登录的组合更是堪称Java安全中的***~( ̄_, ̄ )--但本文只介绍它们三者的整合配置(说白了就是给自己留个学习

shiro 集成spring 配置 学习记录(一)

首先当然是项目中需要增加shiro的架包依赖: 1 <!-- shiro --> 2 <dependency> 3 <groupId>org.apache.shiro</groupId> 4 <artifactId>shiro-core</artifactId> 5 <version>${shiro.version}</version> 6 <exclusions> 7 <exclusion&

Shiro权限注解原理

概述 前不久刚学会使用权限注解(),开始思索了一番.最开始猜测实现方式是注解@Aspect,具体实现方式类似如下所示(切面记录审计日志).后来发现并非如此,所以特地分析一下源码. @Component @Aspect public class AuditLogAspectConfig { @Pointcut("@annotation(com.ygsoft.ecp.mapp.basic.audit.annotation.AuditLog) || @annotation(com.ygsoft.ecp