Shrio04 自定义Realm
1 说明
1.1 Realm的作用
Realm和认证和授权时的数据交互有关,相当于DAO层。
1.2 AuthorizingRealm
》层次关系图
》作用
继承AuthorizingRealm类后重写doGetAuthorizationInfo和doGetAuthenticationInfo就可以实现授权和认证逻辑。
2 代码实现
2.1 创建一个maven项目并引入shiro、junit依赖
2.2 创建一个类继承AuthorizingRealm
2.3 重写doGetAuthorizationInfo和doGetAuthenticationInfo
2.4 完整代码
package com.xunyji.demo04.realm; import com.xunyji.demo0.StringUtilsXyj;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; /**
* @author AltEnter
* @create 2019-01-23 20:32
* @desc 自定义Realm,md
**/
public class CustomRealm extends AuthorizingRealm { private Logger log = LoggerFactory.getLogger(this.getClass()); private Map<String, String> userMap = new HashMap<String, String>(); {
getName();
// userMap.put("fury", "111111");
// userMap.put("fury", "96e79218965eb72c92a549dd5a330112");
userMap.put("fury", "66b747dd6c7c7c8ca4227a67fff8ea6e");
} /**
* 授权逻辑
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 01 获取用户名
String username = (String) principals.getPrimaryPrincipal();
// 02 获取权限集合
Set<String> permissionSet = getPermissionSetByUsername(username);
// 03 获取角色集合
Set<String> roleSet = getRoleSetByUsername(username);
// 04 封装SimpleAuthorizationInfo对象
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setRoles(roleSet);
simpleAuthorizationInfo.setStringPermissions(permissionSet);
return simpleAuthorizationInfo;
} /**
* 根据用户名获取权限集合
* @param username
* @return
*/
private Set<String> getPermissionSetByUsername(String username) {
HashSet<String> permissionSet = new HashSet<>();
permissionSet.add("user:create");
permissionSet.add("user:delete");
permissionSet.add("user:update");
return permissionSet;
} /**
* 根据用户名获取角色集合
* @param username
* @return
*/
private Set<String> getRoleSetByUsername(String username) {
HashSet<String> roleSet = new HashSet<>();
roleSet.add("admin");
roleSet.add("user");
return roleSet;
} /**
* 认证逻辑
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 01 获取前端用户名和密码
String username = (String) token.getPrincipal();
String passoword = new String((char[]) token.getCredentials());
if (StringUtilsXyj.isEmpty(passoword) || StringUtilsXyj.isEmpty(username)) {
String msg = "doGetAuthenticationInfo - 用户名和密码不能为空";
log.info(msg);
throw new RuntimeException(msg);
}
log.info(String.format("doGetAuthenticationInfo - 前端传过来的用户信息为 - 用户名为:%s ,用户密码为:%s", username, passoword));
System.out.println(String.format("doGetAuthenticationInfo - 前端传过来的用户信息为 - 用户名为:%s ,用户密码为:%s", username, passoword)); // 02 根据用户名获取用户密码
String pwd = getPasswordByUsername(username);
// 03 前端密码加密加盐处理
passoword = string2Md5Hash(passoword, "AltEnter");
System.out.println("加盐加密后的密码为:" + pwd); // 04 密码比对
if (passoword.equals(pwd)) {
// 封装SimpleAuthenticationInfo对象
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, passoword, getName());
// 加盐处理
simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("AltEnter"));
return simpleAuthenticationInfo;
} else {
String msg = "doGetAuthenticationInfo - 用户名或者密码错误";
log.info(msg);
System.out.println(msg);
throw new RuntimeException(msg);
}
} /**
* 密码加密加盐处理
* @param password 待加密密码
* @param salt 盐
* @return 经过加密和加盐处理后的密码
*/
private String string2Md5Hash(String password, String salt) {
return new Md5Hash(password, salt).toString();
} /**
* 根据用户名获取密码
* @param username
* @return
*/
private String getPasswordByUsername(String username) {
String pwd = userMap.get(username);
return pwd;
} public static void main(String[] args) {
// Md5Hash md5Hash = new Md5Hash("111111");
// System.out.println("111111加密后的结果为:" + md5Hash.toString());
// 96e79218965eb72c92a549dd5a330112 Md5Hash md5Hash = new Md5Hash("111111", "AltEnter");
System.out.println("111111经过MD5加密和AltEnter加盐后的结果为:" + md5Hash.toString());
// 66b747dd6c7c7c8ca4227a67fff8ea6e
}
}
3 测试类
package com.xunyji.demo04.realm; import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test; import static org.junit.Assert.*; public class CustomRealmTest {
@Test
public void test01() {
CustomRealm customRealm = new CustomRealm();
// shiro加密 start
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
//选择加密方式
matcher.setHashAlgorithmName("md5");
//加密次数
matcher.setHashIterations(1);
// 给自定义Realm设置加密规则
customRealm.setCredentialsMatcher(matcher);
// shiro加密 end // 更改认证策略 start
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
FirstSuccessfulStrategy firstSuccessfulStrategy = new FirstSuccessfulStrategy();
ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
modularRealmAuthenticator.setAuthenticationStrategy(firstSuccessfulStrategy);
defaultSecurityManager.setAuthenticator(modularRealmAuthenticator);
// 更改认证策略 end defaultSecurityManager.setRealm(customRealm); SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken("fury", "111111"); subject.login(token);
System.out.println(String.format("认证信息为:%s", subject.isAuthenticated())); System.out.println(String.format("拥有admin角色吗? - %s", subject.hasRole("admin")));
System.out.println(String.format("拥有user:create权限吗? - %s", subject.isPermitted("user:create"))); subject.logout();
System.out.println(String.format("认证信息为:%s", subject.isAuthenticated())); }
}
4 注意
4.1 可以给SecurityManager设置认证策略

4.2 可以给Realm设置MD5加密

4.3 SecurityManager必须先设置认证策略再设置Realm

Shrio04 自定义Realm的更多相关文章
- 权限框架 - shiro 自定义realm
上篇文章中是使用的默认realm来实现的简单登录,这仅仅只是个demo,真正项目中使用肯定是需要连接数据库的 首先创建自定义realm文件,如下: 在shiro中注入自定义realm的完全限定类名: ...
- Shrio认证详解+自定义Realm
Authentication(身份认证)是Shiro权限控制的第一步,用来告诉系统你就是你. 在提交认证的时候,我们需要给系统提交两个信息: Principals:是一个表示用户的唯一属性,可以是用户 ...
- Shiro第二篇【介绍Shiro、认证流程、自定义realm、自定义realm支持md5】
什么是Shiro shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证.用户授权. spring中有spring security (原名Acegi),是一个权限框架,它和sp ...
- shiro(二)自定义realm,模拟数据库查询验证
自定义一个realm类,实现realm接口 package com; import org.apache.shiro.authc.*; import org.apache.shiro.realm.Re ...
- shiro自定义Realm
1.1 自定义Realm 上边的程序使用的是shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm. ...
- Shiro入门 - 通过自定义Realm连数数据库进行授权
shiro-realm.ini [main] #自定义Realm myRealm=test.shiro.MyRealm #将myRealm设置到securityManager,相当于Spring中的注 ...
- Shiro入门 - 通过自定义Realm连数数据库进行认证(md5+salt形式)
shiro-realm-md5.ini [main] #定义凭证匹配器 credentialsMatcher=org.apache.shiro.authc.credential.HashedCrede ...
- Shiro入门 - 通过自定义Realm连数数据库进行认证
添加shiro-realm.ini文件 [main] #自定义Realm myRealm=test.shiro.MyRealm #将myRealm设置到securityManager,相当于Sprin ...
- shiro教程2(自定义Realm)
通过shiro教程1我们发现仅仅将数据源信息定义在ini文件中与我们实际开发环境有很大不兼容,所以我们希望能够自定义Realm. 自定义Realm的实现 创建自定义Realmjava类 创建一个jav ...
随机推荐
- timer Compliant Controller project (4)layout and gerber, paning
1 LAYOUT 2 Gerber 3 CAM350-Paining
- swift 分页视图
var data:NSArray! var scrollView: UIScrollView! var pageCtrl: UIPageControl! override func viewDidLo ...
- 使用jquery获取url以及jquery获取url参数的方法(转)
使用jquery获取url以及使用jquery获取url参数是我们经常要用到的操作 1.jquery获取url很简单,代码如下 1.window.location.href; 其实只是用到了javas ...
- supervisor 使用tips
Supervisor (http://supervisord.org) 是一个用 Python 写的进程管理工具,可以很方便的用来启动.重启.关闭进程,supervisor可以同时监控多个进程,并可以 ...
- ASP.NET Word转为PDF
1.首先安装 Microsoft Office 2007加载项:Microsoft Save as PDF-简体中文版:下载地址: http://download.microsoft.com/down ...
- nexus 使用Raw Repositories 进行maven site 发布
实际项目中我们可能需要进行maven 项目的site 文档发布,一般的处理是生成之后,然后在进行发布到一个静态 服务器进行页面访问,nexus3 提供了一个Raw Repositories 很方便可以 ...
- Hadoop NameNode 高可用 (High Availability) 实现解析[转]
NameNode 高可用整体架构概述 在 Hadoop 1.0 时代,Hadoop 的两大核心组件 HDFS NameNode 和 JobTracker 都存在着单点问题,这其中以 NameNode ...
- GNU Radio: Multiple USRP configurations 配置多个USRP设备
Introduction 引言 Some USRP devices are capable of being grouped to form a single, virtual device. A s ...
- 黄聪:国内com域名转移到Godaddy详细教程(转)
原文:http://www.cnblogs.com/hsapphire/archive/2010/01/16/1649743.html 最近CCTV进行大量报道色情新闻,还举报CNNIC监管CN域名不 ...
- Keras函数式 API
用Keras定义网络模型有两种方式, Sequential 顺序模型 Keras 函数式 API模型 之前我们介绍了Sequential顺序模型,今天我们来接触一下 Keras 的函数式API模型. ...
