上面一章说到shiro的认证和授权最底层就是调用realm的getAuthorizationInfo(获取用户的角色和资源)和getAuthenticationInfo(校验账号密码是否正确)两个方法。

如果我们要从数据库中查询用户和他的权限信息,我们可以使用shiro提供给我们的JdbcRealm

JdbcRealm

添加jar

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>0.2.23</version>
</dependency>

classpath环境下新建shiro-jdbc.ini如下配置
这里我们采用了阿里巴巴的数据源,注入到jdbcRealm的dataSource变量中,并且将这个jdbcRealm注入到securityManager,有点类似于spring的注入。

下面的sql放在github上对应的章节根目录下,导入即可,数据库密码填写自己数据库密码

jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro
dataSource.username=root
dataSource.password=123456
jdbcRealm.dataSource=$dataSource
#注入securityManager的realm
securityManager.realms=$jdbcRealm

测试代码:

ShiroUtils.login("classpath:shiro-jdbc.ini","zhang","123456");
Subject subject = SecurityUtils.getSubject();
//是否通过认证
System.out.println(subject.isAuthenticated());

其中ShiroUtils的登录方法(这个以后直接略过):

    public static void login(String configPath,String username,String password){
Factory<SecurityManager> factory =new IniSecurityManagerFactory(configPath);
//得到安全管理器
SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try {
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
}

最后输出true。

因为jdbcRealm里面的sql都是固定的,所以我们表结构都要按照JdbcRealm里面创建对应的表。下面是JdbcRealm里面各种查询的sql(salt是密码加密,后面介绍加密再说,我们这里直接用明文密码)

表里面数据分别如下

接着测试代码添加如下:

        System.out.println(subject.hasRole("role1"));

        System.out.println(subject.isPermitted("user:create"));

最后输出true,false

为什么角色role1获取到了,permission没有获取到呢。

原因是JdbcRealm里面有个permissionsLookupEnabled默认是false,所以不会查询对应的资源权限,我们在配置文件中打开这个查询。

#打开permission查询
jdbcRealm.permissionsLookupEnabled=true

再查询就是true了。

自定义Realm

1 新增MyRealm类直接继承AuthorizingRealm.

public class MyRealm extends AuthorizingRealm {

    //认证信息,
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername();
String password = new String(upToken.getPassword());
//模拟用户名密码是否正确
if(!"zhang".equals(username)){
throw new UnknownAccountException();
}
if(!"123456".equals(password)){
throw new IncorrectCredentialsException();
}
return new SimpleAuthenticationInfo(username,password,getName()); } //授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//获取用户名
String username = (String)getAvailablePrincipal(principals);
//模拟从数据库查询出来对应的角色和权限
Set<String> roles = new HashSet<String>();
roles.add("role_1");
roles.add("role_2"); Set<String> permissions = new HashSet<String>();
permissions.add("user:create");
permissions.add("user:delete"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(roles);
info.setStringPermissions(permissions);
return info;
} }

2,classpath文件下新建shiro-myrealm.ini配置文件

myrealm= com.nfcm.shiro.Realm.MyRealm
securityManager.realms=$myrealm

3,测试

        ShiroUtils.login("classpath:shiro-myrealm.ini","zhang","123456");

        Subject subject = SecurityUtils.getSubject();
//是否通过认证
System.out.println(subject.isAuthenticated());
//是否有role1角色
System.out.println(subject.hasRole("role_1")); System.out.println(subject.isPermitted("user:create"));

到这里全部测试通过。

github代码地址

https://github.com/cmniefei/shiroparent

(3)shiro自定义realm的更多相关文章

  1. 权限框架 - shiro 自定义realm

    上篇文章中是使用的默认realm来实现的简单登录,这仅仅只是个demo,真正项目中使用肯定是需要连接数据库的 首先创建自定义realm文件,如下: 在shiro中注入自定义realm的完全限定类名: ...

  2. shiro自定义Realm

    1.1 自定义Realm 上边的程序使用的是shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm. ...

  3. shiro自定义realm支持MD5算法认证(六)

    1.1     散列算法 通常需要对密码 进行散列,常用的有md5.sha, 对md5密码,如果知道散列后的值可以通过穷举算法,得到md5密码对应的明文. 建议对md5进行散列时加salt(盐),进行 ...

  4. shiro自定义realm认证(五)

    上一节介绍了realm的作用: realm:需要根据token中的身份信息去查询数据库(入门程序使用ini配置文件),如果查到用户返回认证信息,如果查询不到返回null.token就相当于是对用户输入 ...

  5. Shiro自定义Realm时用注解的方式注入父类的credentialsMatcher

    用Shiro做登录权限控制时,密码加密是自定义的. 数据库的密码通过散列获取,如下,算法为:md5,盐为一个随机数字,散列迭代次数为3次,最终将salt与散列后的密码保存到数据库内,第二次登录时将登录 ...

  6. Shiro自定义realm实现密码验证及登录、密码加密注册、修改密码的验证

    一:先从登录开始,直接看代码 @RequestMapping(value="dologin",method = {RequestMethod.GET, RequestMethod. ...

  7. shiro中自定义realm实现md5散列算法加密的模拟

    shiro中自定义realm实现md5散列算法加密的模拟.首先:我这里是做了一下shiro 自定义realm散列模拟,并没有真正链接数据库,因为那样东西就更多了,相信学到shiro的人对连接数据库的一 ...

  8. Shiro笔记(四)Shiro的realm认证

    认证流程: 1.获取当前Subject.调用SecurityUtils.getSubject(); 2.测试当前用户是否已经被认证,即是否已经登录,调用Subject的isAurhenticated( ...

  9. 自定义shiro的Realm实现和CredentialsMatcher实现以及Token实现

    Realm是shiro比较核心的接口,简单说它的实现类就是校验用户输入的账号信息的地方.如果想自定义实现一般的配置文件如下: <!--自定义Realm 继承自AuthorizingRealm - ...

随机推荐

  1. Angular 4 路由时传递数据

    路由时传递数据的方式有 1. 在查询参数中传递数据 2. 在路由路径中传递参数 3. 在路由配置中传递参数 一.在查询参数中传递数据 在前一节的基础上,我们增加路由数据传递 2. 接收参数的地方 3. ...

  2. DKhadoop大数据系统架构设计方案

    大数据作为当下最为热门的事件之一,其实已经不算是很新鲜的事情了.如果是三五年前在讨论大数据,那可能会给人一种很新鲜的感觉.大数据作为当下最为重要的一项战略资源,已经是越来越得到国家和企业的高度重视,我 ...

  3. Elasticsearch 基础入门

    原文地址:Elasticsearch 基础入门 博客地址:http://www.extlight.com 一.什么是 ElasticSearch ElasticSearch是一个基于 Lucene 的 ...

  4. 启动ECLIPSE时,提示找到不 eclipse\jre\bin\javaw.exe

    原因:在PATH中未配置 jre\bin目录 %JAVA_HOME%\jre\bin - 无论是用:D:\Asoft\Java\jdk1.7.0_45\jre\bin 还是:D:\Asoft\Java ...

  5. Android 对话框(Dialog)大全

    转自: http://www.cnblogs.com/salam/archive/2010/11/15/1877512.html Activities提供了一种方便管理的创建.保存.回复的对话框机制, ...

  6. 关于分布式锁Java常用技术方案

    前言:       由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.      所以自己结合实际工作中的一些经验和网上 ...

  7. Missing Number @leetcode

    Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missin ...

  8. chronyd时间服务器同步时间配置

    chrony是两个用来维持计算机系统时钟准确性的程序,这两个程序命名为chronyd和chronyc. chronyd是一个在系统后台运行的守护进程.他根据网络上其他时间服务器时间来测量本机时间的偏移 ...

  9. javascript事件处理程序的3个阶段

    第一阶段:HTML事件处理阶段.就是在元素里面添加onclick之类的属性来调用某个函数. <input type="button" value="单击" ...

  10. .Net2.0部署在IIS8.5上的问题

     请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理. 到"应用程序池"里找网站对应的应用程序池(右击网站-> 高级设置),双击程序池, 看程序池是否也网站的net ...