本文来自网易云社区

作者:王飞

以上的配置走完以后就可以用,下面讲讲个人需求,以及踩过的坑:

1、如何修改cookie的名称,默认名称“rememberMe”太丑了有木有?

首先丢一篇文章,关于改cookie的:http://blog.csdn.net/lhacker/article/details/19341735

我的理解是Shiro 的 SimpleCookie 其实提供了修改cookie名称的方法,方法有两个:

一是直接通过构造函数的方法修改cookie的名称,就像我展示的配置文件shiro的中一样:

1 <constructor-arg value="COOKIE_NAME" />

其实调用的是SimpleCookie这个方法:

1     public SimpleCookie(String name) {
2         this();
3         this.name = name;
4     }
SimpleCookie 其实还提供了其它构造方法可以使用,详见源码。

第二个方法则是通过给SimpleCookie的name字段赋值的方法,这个方法就和我给的链接中的方法一样:

1 <property name="name" value="COOKIE_NAME" />

除此之外,还可以配置SimpleCookie的其它字段,源码中给出的可以配置字段如下:

1     private String name;
2     private String value;3     private String comment;
4     private String domain;
5     private String path;
6     private int maxAge;
7     private int version;
8     private boolean secure;
9     private boolean httpOnly;

2、明明配置了权限注解,为什么没有调用doGetAuthorizationInfo获取授权信息的方法?

注解生效需要在servlet.xml中配置如下:

      <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager" />
    </bean>

3、一个接口可以被不同的页面调用,但这个页面分别属于不同的权限?

我们在使用权限注解时,往往会遇到这样的问题,接口可以重复使用,权限却要分开,怎么办呢?

首先看看@RequiresPermissions注解的源码:

  1 @Target({ElementType.TYPE, ElementType.METHOD})
 2 @Retention(RetentionPolicy.RUNTIME)
 3 public @interface RequiresPermissions {
 4 
 5     /**
 6      * The permission string which will be passed to {@link org.apache.shiro.subject.Subject#isPermitted(String)}
 7      * to determine if the user is allowed to invoke the code protected by this annotation.
 8      */
 9     String[] value();
10     
11     /**
12      * The logical operation for the permission checks in case multiple roles are specified. AND is the default
13      * @since 1.1.0
14      */
15     Logical logical() default Logical.AND; 
16 
17 }

源码很简单,不难发现,注解中权限的key存放在value数组中,另外还有一个Logical用来存放多个权限之间关系,所以当我们一个方法需要满足多个权限时,可以这样:

@RequiresPermissions(value = { "key1", "key2" }, logical = Logical.AND)

当一个方法满足任意权限key时,可以这样

@RequiresPermissions(value = { "key1", "key2" }, logical = Logical.OR)

4、采用非用户密码的方式登录怎么办?

遇到这个问题,我的处理办法是验证方式我们事先处理掉,然后再调用subject的login,大致流程如下:

// 处理登录逻辑
验证手机验证码等......
// 调用subject login
UsernamePasswordToken token = new UsernamePasswordToken(
                    email, "openid", true);
// username 字段可以放id/账号/手机号/邮箱等唯一值
// password  则存放一个当前账号必带的一个信息,若有在验证过程中有密码则可以存放密码,可以直接存放任意string,这个都没关系,这里就存放了一个string字符"openid"
SecurityUtils.getSubject().login(token);

subject 的 login方法会间接调用到doGetAuthenticationInfo获取验证相关信息的方法,上面给出了一个方法的源码

 1 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
 2         try {
 3             UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
 4             String email = token.getUsername();
 5             String password = new String(token.getPassword());
 6             if (!StringUtils.isEmpty(email) && "openid".equals(password)) {
 7 // 这里做简单的判断,username不为空,且 password 为我们给定的字符串
 8 // 如果是则可以进行权限验证,否则失败
 9 // 这里除了放username 还可以放其它内容,也可以将整个user的信息从数据库取出来,放入SimpleAuthenticationInfo的principal字段中
10                 return new SimpleAuthenticationInfo("希望存入cookie的内容","openid", getName());
11             }
12             logger.info("登录验证失败,shiro 不添加权限信息");
13             return null;
14         } catch (Exception e) {
15             logger.error("shiro 身份验证异常:", e);
16             return null;
17         }
18     }

5、存入cookie的数据无法序列化?

放入放入SimpleAuthenticationInfo的principal字段常常遇到序列化的问题,这是由于我们平时写的model都没有实现Serializable,所以我们只要让对应的model实现一下即可,如:

1 public class User implements Serializable{
2      ......      
3 }

6、shiro.xml中配置和注解分别做啥用?

注解和shiro.xml中配置的filter是shiro提供的两套权限验证流程,他们的调用并不一样

这篇文档对filter中的相关注解错了比较详细的介绍:http://blog.csdn.net/clj198606061111/article/details/24185023

我截取一段关于shiro.xml中关于ShiroFilterFactoryBean配置的说明,如下:

securityManager:这个属性是必须的。

loginUrl:没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面。

successUrl:登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此。

unauthorizedUrl:没有权限默认跳转的页面。

过滤器简称

对应的java类

anon

org.apache.shiro.web.filter.authc.AnonymousFilter

authc

org.apache.shiro.web.filter.authc.FormAuthenticationFilter

authcBasic

org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter

perms

org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter

port

org.apache.shiro.web.filter.authz.PortFilter

rest

org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter

roles

org.apache.shiro.web.filter.authz.RolesAuthorizationFilter

ssl

org.apache.shiro.web.filter.authz.SslFilter

user

org.apache.shiro.web.filter.authc.UserFilter

logout

org.apache.shiro.web.filter.authc.LogoutFilter

anon:例子/admins/**=anon 没有参数,表示可以匿名使用。

authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数

roles:例子/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。

perms:例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。

rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。

port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString

是你访问的url里的?后面的参数。

authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证

ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https

user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查

注:anon,authcBasic,auchc,user是认证过滤器,

perms,roles,ssl,rest,port是授权过滤器

注解中的权限信息,则是通过获取授权信息方法实现:

@Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        try {
            Iterator<String> iter = principals.fromRealm(getName()).iterator();
            if (!iter.hasNext()) {
                logger.info("shiro 验证 无权限");
                return null;
            }
            String email = iter.next();
            if (!Strings.isNullOrEmpty(email)) {
                // 通过email可以实时获取权限信息,当然也可以在iter中本身就带有权限信息,不在进行数据库或者redis的查询
        // set auth
                SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
                info.addStringPermissions(new ArrayList<String>("权限集合"));
                return info;
            }
            logger.info("邮箱为空");
            return null;
        } catch (Exception e) {
            logger.error("shiro 权限获取异常:", e);
            return null;
        }
    }

总结:

第一次使用shiro做权限验证,个人感觉shiro的权限验证比较灵活易懂,且比较适合新手接入,权限的控制也比较简单。上面提出的几个问题,即是本人在随着项目的所遇到的问题,只是给出了个人的解决方法,若有更适合的方法还请指出,多谢。

网易云免费体验馆,0成本体验20+款云产品!

更多网易研发、产品、运营经验分享请访问网易云社区

相关文章:
【推荐】 一行代码搞定Dubbo接口调用

小白用shiro(2)的更多相关文章

  1. 小白用shiro(1)

    本文来自网易云社区 作者:王飞 首先引入一段关于shiro的介绍: 开发系统中,少不了权限,目前java里的权限框架有SpringSecurity和Shiro(以前叫做jsecurity),对于Spr ...

  2. 数据库路由中间件MyCat - 使用篇(4)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 配置MyCat 3. 配置conf/rule.xml 1.5GA版本中的规则配置比较笨,2.0中优化了一些, ...

  3. Spring Boot 学习系列(09)—自定义Bean的顺序加载

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Bean 的顺序加载 有些场景中,我们希望编写的Bean能够按照指定的顺序进行加载.比如,有UserServ ...

  4. shiro的小白学习

    1. shiro是啥就不用说了吧 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理 SecurityManager 是shiro的核心.它不同于java. ...

  5. spring-boot整合shiro作权限认证

    spring-shiro属于轻量级权限框架,即使spring-security更新换代,市场上大多数企业还是选择shiro 废话不多说  引入pom文件 <!--shiro集成spring--& ...

  6. 一套基于SpringBoot+Vue+Shiro 前后端分离 开发的代码生成器

    一.前言 最近花了一个月时间完成了一套基于Spring Boot+Vue+Shiro前后端分离的代码生成器,目前项目代码已基本完成 止步传统CRUD,进阶代码优化: 该项目可根据数据库字段动态生成 c ...

  7. 关于postman与shiro权限验证问题

    作为一个java的开发小白 , 写完一个web方法测试是必不可少的 , 只有测试号没问题的方法给别人时 ,别人才不知道你是小白 , 要不然很尴尬的 .新手入坑的测试工具是postman .这个工具用起 ...

  8. Shiro Demo 示例(SpringMVC-Mybatis-Shiro-redis)

    Shiro Demo 准备工作 运行前申明 请看完本页面的所有细节,对你掌握这个项目来说很重要,别一上来就搞,你不爽,我也不爽. 本项目需要一定的Java功底,需要对SpringMvc,Mybatis ...

  9. SpringBoot+Shiro学习(七):Filter过滤器管理

    SpringBoot+Shiro学习(七):Filter过滤器管理 Hiwayz 关注  0.5 2018.09.06 19:09* 字数 1070 阅读 5922评论 1喜欢 20 先从我们写的一个 ...

随机推荐

  1. jq中的attr和prop属性

    今天在做checkbox的全选等功能时刚开始用的是 $('input[type='checkbox']").attr("checked","true" ...

  2. 关于php和docker

    Docker在PHP项目开发环境中的应用 http://www.wolonge.com/zhuanlan/detail/117441 Docker在PHP项目开发环境中的应用 http://linux ...

  3. hihocoder1829 Tomb Raider

    思路: 暴力枚举. 实现: #include <iostream> #include <set> #include <vector> using namespace ...

  4. arcgis jsapi接口入门系列(7):鼠标在地图画线

    初始化,每个map执行一次就行 drawPolylineInit: function () { //画几何对象初始化 //新建一个图形图层用于存放画图过程中的图形 let layer = new th ...

  5. Ubuntu 16.04 not a com32r image

    安装Ubuntu16.04,出现题目中的错误,解决方法如下 重点:开机后按TAB键,在随后出现的命令行提示符中输入live 既可,之后的过程就是正常的过程了!

  6. LR中webservice服务测试的脚本

    Action(){ /* 测试QQ是否在线的功能接口 输入参数:QQ号码 String,默认QQ号码:8698053. 返回数据:String,Y = 在线:N = 离线:E = QQ号码错误:A = ...

  7. Openjudge 2.5 6264:走出迷宫

    总时间限制:  1000ms 内存限制:  65536kB 描述 当你站在一个迷宫里的时候,往往会被错综复杂的道路弄得失去方向感,如果你能得到迷宫地图,事情就会变得非常简单. 假设你已经得到了一个n* ...

  8. (转)MyBatis框架的学习(四)——Mapper.xml文件中的输入和输出映射以及动态sql

    http://blog.csdn.net/yerenyuan_pku/article/details/71893689 前面对MyBatis框架的学习中,我们对Mapper.xml映射文件多少有些了解 ...

  9. python_111_动态导入模块

    lib下aa.py文件内容: class C: def __init__(self): self.name='alex' from lib import aa#正常导入 print(aa.C) 动态导 ...

  10. CS 分解

    将学习到什么 CS 分解是分划的酉矩阵在分划的酉等价之下的标准型. 它的证明涉及奇异值分解.QR 分解以及一个简单习题.   一个直观的习题 设 \(\Gamma, L \in M_p\). 假设 \ ...