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

 

posted @ 2019-05-07 15:25  X凯  阅读(552)  评论(0编辑  收藏  举报