写在前面的话:

我之前写过两篇与shiro安全框架有关的博文,居然能够广受欢迎实在令人意外。说明大家在互联网时代大伙对于安全和登录都非常重视,无论是大型项目还是中小型业务,普遍都至少需要登录与认证的逻辑封装。相较于SpringSecurity而言,Shrio更轻量无过多依赖和便于独立部署的特点更收到开发者的欢迎。本篇博客只作为前两篇对于shiro使用的基础补充,我只谈谈如何在springboot项目中配置多角色验证。

一、场景介绍

假设在我们的项目中需要有前台用户登录和后台系统管理员登录两种验证方式。当然在传统的业务逻辑中用户和管理员可以使用不同的角色加以区分,假设现在的逻辑是用户与系统管理员分别保存在不同的表中并且也分别对应了不同的角色(role)与权限(permission)。换句话说,从业务上看相同的用户名和密码如果是在前台页面登录可能对应的是普通用户,从后台登录则对应某板块的系统管理。面对这样的需求我们可以在shiro框架中配置多个realm,再配合上认证策略来执行。

二、代码讲解

与单一realm相同,首先根据不同的登录认证要求创建不同的realm。这里只提供作为后台系统管理员的realm代码实例:

// 系统管理员专用
public class AdministratorRealm extends AuthorizingRealm {
@Autowired
private AdministratorRegisterService administratorRegisterService;
@Autowired
private PasswordSupport passwordSupport; @Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
String username = (String) principals.getPrimaryPrincipal();
Administrator administrator = administratorRegisterService.getAdministratorByName(username);
for (Role r : administrator.getRoles()) {
authorizationInfo.addRole(r.getRoleName());
}
return authorizationInfo;
} @Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
Administrator administrator = administratorRegisterService.getAdministratorByName(username);
if (administrator == null) {
throw new UnknownAccountException();
}
if (administrator.isLocked()) {
throw new LockedAccountException();
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(administrator.getUsername(),
administrator.getPassword(), ByteSource.Util.bytes(passwordSupport.credentialsSalt(administrator)),
getName()); return authenticationInfo;
} }

doGetAuthenticationInfo方法负责用户名和密码验证,doGetAuthorizationInfo方法负责角色和权限的分配, passwordSupport是一个自定义的类负责password加密和生成salt功能。

/**
* 密码辅助方法
*
* @author learnhow
*
*/
@Component
public class PasswordSupport {
public static final String ALGORITHM_NAME = "md5";
public static final int HASH_ITERATIONS = 2;/**
* 针对系统管理生成salt和加密密码
*
* @param administrator
*/
public void encryptPassword(Administrator administrator) {
administrator.setSalt(new SecureRandomNumberGenerator().nextBytes().toHex());
String newPassword = new SimpleHash(ALGORITHM_NAME, administrator.getPassword(),
ByteSource.Util.bytes(credentialsSalt(administrator)), HASH_ITERATIONS).toHex();
administrator.setPassword(newPassword);
}/**
* 对Administrator的salt生成规则
*
* @param administrator
* @return
*/
public String credentialsSalt(Administrator administrator) {
return administrator.getSalt() + administrator.getEmail();
}
}

AdministratorRegisterService是服务组件负责通过name从数据库中查询。

在Shiro中无论是单一realm还是多个realm都需要对SecurityManager进行配置。

@Configuration
public class ShiroConfig {
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName(PasswordSupport.ALGORITHM_NAME);
hashedCredentialsMatcher.setHashIterations(PasswordSupport.HASH_ITERATIONS);
return hashedCredentialsMatcher;
} @Bean
public AdministratorRealm getAdministatorRealm() {
AdministratorRealm realm = new AdministratorRealm();
realm.setName("AdministratorRealm");
realm.setCredentialsMatcher(hashedCredentialsMatcher());
return realm;
} @Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
modularRealmAuthenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
securityManager.setAuthenticator(modularRealmAuthenticator); List<Realm> realms = new ArrayList<>();
// TODO-多个realms进配置在这里
realms.add(getAdministatorRealm());
securityManager.setRealms(realms);
return securityManager;
}
}

ModularRealmAuthenticator的setAuthenticationStrategy方法中配置认证策略。Shiro提供了三种策略:AllSuccessFulStrategy, AtLeastOneSuccessFulAtrategy, FirstSuccessFulStrategy,默认使用AtLeastOneSuccessFulAtrategy,通常不需要特别配置。

三、注意事项

1.多realm认证只会抛出AuthenticationException,因此如果要想在外部判断到底是在认证的哪一步发生的错误需要自己定义一些异常类型。

2.shiro没有提供根据条件指定realm的功能,如果需要实现这样的功能只能通过继承与重写来实现,这里没有涉及需要深入探讨的同学最好根据自己的实际情况专门研究。

写在后面的话:

最近有不少朋友在看了我的博客以后加我的QQ或者发邮件要求提供演示源码,为了方便交流我索性建了一个技术交流群,今后有些源码我可能就放群资料里面了。当然之前的一些东西还在补充中,有些问题也希望大伙能共同交流。QQ群号:960652410

30分钟了解Shiro与Springboot的多Realm基础配置的更多相关文章

  1. 30分钟带你了解Springboot与Mybatis整合最佳实践

    前言:Springboot怎么使用想必也无需我多言,Mybitas作为实用性极强的ORM框架也深受广大开发人员喜爱,有关如何整合它们的文章在网络上随处可见.但是今天我会从实战的角度出发,谈谈我对二者结 ...

  2. Shiro (Shiro + JWT + SpringBoot应用)

    Shiro (Shiro + JWT + SpringBoot应用) 目录 Shiro (Shiro + JWT + SpringBoot应用) 1.Shiro的简介 2.Shiro + JWT + ...

  3. 转:30分钟了解Springboot整合Shiro

    引自:30分钟了解Springboot整合Shiro 前言:06年7月的某日,不才创作了一篇题为<30分钟学会如何使用Shiro>的文章.不在意之间居然斩获了22万的阅读量,许多人因此加了 ...

  4. 30分钟学会如何使用Shiro

    本篇内容大多总结自张开涛的<跟我学Shiro>原文地址:http://jinnianshilongnian.iteye.com/blog/2018936 我并没有全部看完,只是选择了一部分 ...

  5. 转:30分钟学会如何使用Shiro

    引自:http://www.cnblogs.com/learnhow/p/5694876.html 本篇内容大多总结自张开涛的<跟我学Shiro>原文地址:http://jinniansh ...

  6. 30分钟学会如何使用Shiro(转自:http://www.cnblogs.com/learnhow/p/5694876.html)

    本篇内容大多总结自张开涛的<跟我学Shiro>原文地址:http://jinnianshilongnian.iteye.com/blog/2018936 我并没有全部看完,只是选择了一部分 ...

  7. 30分钟学会如何使用Shiro(转)

    本文转自http://www.cnblogs.com/learnhow/p/5694876.html 感谢作者 本篇内容大多总结自张开涛的<跟我学Shiro>原文地址:http://jin ...

  8. 30分钟学会如何使用Shiro(转)

    本篇内容大多总结自张开涛的<跟我学Shiro>原文地址:http://jinnianshilongnian.iteye.com/blog/2018936 我并没有全部看完,只是选择了一部分 ...

  9. 30分钟学会使用Spring Web Services基础开发

    时隔一年终于又推出了一篇30分钟系列,上一篇<30分钟学会反向Ajax>是2016年7月的事情了.时光荏苒,岁月穿梭.虽然一直还在从事Java方面的开发工作,但是私下其实更喜欢使用C++. ...

随机推荐

  1. Vim/Vi的使用

     Vim 是vi的加强 Gvim图形化的vim Vim/Vi简介 Vim/Vi是一个功能强大的全屏幕文本编辑器,是Linux/Unix上最常用的文本编辑器,他们 的作用是建立,编辑,显示文本文件 Vi ...

  2. rpgmakermv(6) YEP_ItemSynthesis.js物品合成插件

    物品合成插件. 用途?太多了呢. 低级宝石合成高级,还有装备,武器,药水等等. ============================================================ ...

  3. zw版【转发·台湾nvp系列Delphi例程】HALCON FastThreshold2

    zw版[转发·台湾nvp系列Delphi例程]HALCON FastThreshold2 FastThreshold_Delphi_2.PNG procedure TForm1.Button1Clic ...

  4. IO(基础知识)

        IO流类的构造方法决定是输入流还是输出流.输入流连接一个文件,它会将文件中的内容读到流里面,read方法是将流里面的内容     往外读.输出流连接一个文件,它的write方法,是将内存中的内 ...

  5. zendstudio中加入对tpl文件的支持,用HTML Editor编辑器编辑

    zendstudio中加入对tpl文件的支持,用HTML Editor编辑器编辑:ThinkPHP中默认使用的tpl在zendstudio中默认打开都是文本编辑器的,没有语法提示开发效率很低,直接设置 ...

  6. QTQuick控件基础(2)

    import QtQuick 2.2import QtQuick.Controls 1.2import QtQuick.Window 2.1ApplicationWindow {    visible ...

  7. 20144303石宇森 《网络对抗》 WEB基础实践

    20144303石宇森 <网络对抗> WEB基础实践 实验后回答问题 一.什么是表单 表单是一个包含表单元素的区域.用form来定义. HTML是静态显示网页的,无法跟服务器进行交互,所以 ...

  8. 20165310_Exp2实验二《Java面向对象程序设计》

    实验二<Java面向对象程序设计> TDD与单元测试 前期准备: 什么是单元测试? 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证.对于单元测试中单元的含 ...

  9. 2018-2019-1 20189218《Linux内核原理与分析》第四周作业

    构造简单的Linux内核 显然用实验楼配好的环境做这个实验太简单了,按照没有困难制造困难也要上的原则,在自己的64位虚拟机上做这个实验. 按照课本(视频)上的步骤一直做下去,到编译生成init时出现了 ...

  10. 使用CSP防止XSS攻击

    转载自阮一峰博客:http://www.ruanyifeng.com/blog/2016/09/csp.html 跨域脚本攻击 XSS 是最常见.危害最大的网页安全漏洞. 为了防止它们,要采取很多编程 ...