INI配置

从之前的Shiro架构图可以看出,Shiro是从根对象SecurityManager进行身份验证和授权的;也就是所有操作都是自它开始的,这个对象是线程安全且真个应用只需要一个即可,因此Shiro提供了SecurityUtils让我们绑定它为全局的,方便后续操作。因为Shiro的类都是POJO的,因此都很容易放到任何IoC容器管理。但是和一般的IoC容器的区别在于,Shiro从根对象securityManager开始导航;Shiro支持的依赖注入:public空参构造器对象的创建、setter依赖注入。

DefaultSecurityManager securityManager = new DefaultSecurityManager();
//设置authenticator
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
securityManager.setAuthenticator(authenticator); //设置authorizer
ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
authorizer.setPermissionResolver(new WildcardPermissionResolver());
securityManager.setAuthorizer(authorizer); //设置Realm
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/shiro");
ds.setUsername("root");
ds.setPassword(""); JdbcRealm jdbcRealm = new JdbcRealm();
jdbcRealm.setDataSource(ds);
jdbcRealm.setPermissionsLookupEnabled(true);
securityManager.setRealms(Arrays.asList((Realm) jdbcRealm)); //将SecurityManager设置到SecurityUtils 方便全局使用
SecurityUtils.setSecurityManager(securityManager); Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
subject.login(token);
Assert.assertTrue(subject.isAuthenticated());

对应的配置文件

[main]
#authenticator
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
authenticationStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
authenticator.authenticationStrategy=$authenticationStrategy
securityManager.authenticator=$authenticator #authorizer
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver
authorizer.permissionResolver=$permissionResolver
securityManager.authorizer=$authorizer #realm
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro
dataSource.username=root
#dataSource.password=
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
jdbcRealm.permissionsLookupEnabled=true
securityManager.realms=$jdbcRealm

MD5加密,shiro不止这一个加密方式,还有很多方式,如果需要可以自行查阅

@Test//测试加密解密
public void testCode(){
String str = "hello";
String base64Encoded = Base64.encodeToString(str.getBytes());
String str2 = Base64.decodeToString(base64Encoded);
Assert.assertEquals(str, str2); //编码code String str3 = "hello";
String salt = "123";
String salt2 = "234";
String md5 = new Md5Hash(new Md5Hash(str3,salt), salt2).toString();//简单二次加密,不可逆,用于密码验证,还可以转换为 toBase64()/toHex()
System.out.println(new Md5Hash(str3));
System.out.println(md5);
}

连接数据库,使用数据库进行加密登录验证,包括提供缓存,限制失败次数

ini配置

#shiro-password.ini
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=oracle.jdbc.OracleDriver
dataSource.url=jdbc:oracle:thin:@127.0.0.1:1521:ORCL
dataSource.username=userstudy
dataSource.password=s836659812S #credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher=code.RetryLimitHashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName=md5
credentialsMatcher.hashIterations=1
credentialsMatcher.storedCredentialsHexEncoded=true

#jdbcRealm=code.MyRealm 这种是使用自定义realm来进行验证的方式
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
jdbcRealm.permissionsLookupEnabled=true
jdbcRealm.saltStyle=COLUMN#这个直接用会错误,需要bean注册转型
jdbcRealm.authenticationQuery=select password,salt from shiro where users = ?
jdbcRealm.credentialsMatcher=$credentialsMatcher
securityManager.realms=$jdbcRealm
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {

    private Ehcache passwordRetryCache;

    public RetryLimitHashedCredentialsMatcher() {
CacheManager cacheManager = CacheManager.newInstance(CacheManager.class.getClassLoader().getResource("ehcache.xml"));
passwordRetryCache = cacheManager.getCache("passwordRetryCache");
} @Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
String username = (String)token.getPrincipal();
//retry count + 1
Element element = passwordRetryCache.get(username);
if(element == null) {
element = new Element(username , new AtomicInteger(0));
passwordRetryCache.put(element);
}
AtomicInteger retryCount = (AtomicInteger)element.getObjectValue();
if(retryCount.incrementAndGet() > 5) {
//if retry count > 5 throw
throw new ExcessiveAttemptsException();
} boolean matches = super.doCredentialsMatch(token, info);
if(matches) {
//clear retry count
passwordRetryCache.remove(username);
}
return matches;
}
}
public class MyRealm extends AuthorizingRealm {

    private PasswordService passwordService;

    public void setPasswordService(PasswordService passwordService) {
this.passwordService = passwordService;
} @Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) { return null;
} @Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
return new SimpleAuthenticationInfo("sheng",passwordService.encryptPassword("zhi"),getName());
} }
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es">
<diskStore path="java.io.tmpdir"/>
<!-- 登录记录缓存 锁定10分钟 -->
<cache name="passwordRetryCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
</ehcache>

缓存机制现在还不懂,先跳过

package code;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.converters.AbstractConverter;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test; public class TestCode { /*
@Test//测试加密解密
public void testCode(){
String str = "hello";
String base64Encoded = Base64.encodeToString(str.getBytes());
String str2 = Base64.decodeToString(base64Encoded);
Assert.assertEquals(str, str2); //编码code String str3 = "hello";
String salt = "123";
String salt2 = "234";
String md5 = new Md5Hash(new Md5Hash(str3,salt), salt2).toString();//简单二次加密,不可逆,用于密码验证,还可以转换为 toBase64()/toHex()
System.out.println(new Md5Hash(str3));
System.out.println(md5);
}
*/ /*
@Test
public void testCode(){ login("classpath:shiro-password.ini","sheng","z1hi");
}
*/
@Test
public void jdbcPassTest(){//此处还要注意Shiro默认使用了apache commons BeanUtils,默认是不进行Enum类型转型的,此时需要自己注册一个Enum转换器
BeanUtilsBean.getInstance().getConvertUtils().register(new EnumConverter(), JdbcRealm.SaltStyle.class);
String str3 = "567";
String salt = "123";
String salt2 = "123";
String md5 = new Md5Hash(str3,salt).toString();//一次md5+盐,用于验证密码多少
System.out.println(md5);
for(int i = 1; i <= 5; i++) {
try {
login("classpath:shiro-jdbc-pass.ini","zhizhi","566");
} catch (Exception e) {/*ignore*/}
} login("classpath:shiro-jdbc-pass.ini","zhizhi","566");//经过五次失败后没有错误提示,被锁了起来。 } private void login(String path, String name, String password) {
// 1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory(
path);
// Factory<org.apache.shiro.mgt.SecurityManager> factory = new
// IniSecurityManagerFactory("classpath:shiro.ini");
// 2、得到SecurityManager实例 并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory
.getInstance();
SecurityUtils.setSecurityManager(securityManager);
// 3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(name, password);
try {
// 4、登录,即身份验证
subject.login(token);
System.out.println("login success");
} catch (AuthenticationException e) {
// 5、身份验证失败
System.out.println("login file."+e.getMessage()); }
//Assert.assertEquals(true, subject.isAuthenticated()); // 断言用户已经登录
// 6、退出
// subject.logout();
} private class EnumConverter extends AbstractConverter {
@Override
protected String convertToString(final Object value) throws Throwable {
return ((Enum) value).name();
}
@Override
protected Object convertToType(final Class type, final Object value) throws Throwable {
return Enum.valueOf(type, value.toString());
} @Override
protected Class getDefaultType() {
return null;
} }
}

shiro学习笔记(四) ini配置以及加解密的更多相关文章

  1. Shiro学习笔记四(Shiro集成WEB)

    这两天由于家里出了点事情,没有准时的进行学习.今天补上之前的笔记 -----没有学不会的技术,只有不停找借口的人 学习到的知识点: 1.Shiro 集成WEB 2.基于角色的权限控制 3.基于权限的控 ...

  2. Jmeter学习笔记(四)配置元件之计数器

    在接口测试中,有时候需要重复跑一个接口,里面的某个参数的值不能每次都一样,这个时候我们可以使用计数器来实现,名称+计数器. 1.线程组->添加->配置元件->计数器 2.添加效果如下 ...

  3. kvm虚拟化学习笔记(四)之kvm虚拟机日常管理与配置

    KVM虚拟化学习笔记系列文章列表----------------------------------------kvm虚拟化学习笔记(一)之kvm虚拟化环境安装http://koumm.blog.51 ...

  4. Shiro学习笔记总结,附加" 身份认证 "源码案例(一)

    Shiro学习笔记总结 内容介绍: 一.Shiro介绍 二.subject认证主体 三.身份认证流程 四.Realm & JDBC reaml介绍 五.Shiro.ini配置介绍 六.源码案例 ...

  5. Shiro学习笔记(5)——web集成

    Web集成 shiro配置文件shiroini 界面 webxml最关键 Servlet 測试 基于 Basic 的拦截器身份验证 Web集成 大多数情况.web项目都会集成spring.shiro在 ...

  6. shiro学习笔记_0600_自定义realm实现授权

    博客shiro学习笔记_0400_自定义Realm实现身份认证 介绍了认证,这里介绍授权. 1,仅仅通过配置文件来指定权限不够灵活且不方便.在实际的应用中大多数情况下都是将用户信息,角色信息,权限信息 ...

  7. go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk [断剑重铸之日,骑士归来之时])

    目录 go微服务框架kratos学习笔记五(kratos 配置中心 paladin config sdk [断剑重铸之日,骑士归来之时]) 静态配置 flag注入 在线热加载配置 远程配置中心 go微 ...

  8. Java IO学习笔记四:Socket基础

    作者:Grey 原文地址:Java IO学习笔记四:Socket基础 准备两个Linux实例(安装好jdk1.8),我准备的两个实例的ip地址分别为: io1实例:192.168.205.138 io ...

  9. 学习笔记_J2EE_SpringMVC_03_注解配置_@RequestMapping用法

    @RequestMappingde的用法 摘要: 主要介绍注解@RequestMapping的用法 一.@RequestMapping 简介 在Spring MVC 中使用 @RequestMappi ...

随机推荐

  1. You Don't Know JS: Scope & Closures (第一章:什么是Scope)

    Content What is Scope? Lexical Scope Function Vs. Block Scope Hoisting Scope Closures Appendix: Dyna ...

  2. android--------实现Activity和Fragment通信的面向对象的万能接口

    前言 开发一个app时,常用Activity和Fragment,由于操作方便Fragment越来越受欢迎,这样就避免不了Activity和Fragment.Fragment和Fragment之间的通信 ...

  3. Pudding Monsters CodeForces - 526F (分治, 双指针)

    大意: n*n棋盘, n个点有怪兽, 求有多少边长为k的正方形内恰好有k只怪兽, 输出k=1,...,n时的答案和. 等价于给定n排列, 对于任意一个长为$k$的区间, 若最大值最小值的差恰好为k, ...

  4. dp 二维乃至多维背包

    洛谷P1855 榨取kkksc03 分析:套路是很明显的01背包,但是这时受约束的变量有两个了,这种情况下就该用多维背包了 分析方法一样的,用dp[i][j][k]表示从前i个愿望中挑选总时间和总金钱 ...

  5. Python Signal 信号

    https://blog.csdn.net/kongxx/article/details/50976802 http://blog.itpub.net/7728585/viewspace-214206 ...

  6. link标签实现给网页标题前加一个小图标favicon.ico

    使用方法如下:1.<link rel="shortcut icon " type="images/x-icon" href="./favicon ...

  7. windows中安装liunx虚拟机

    我感觉这个写的很好,所以本内容是转他人的内容. http://www.csdn.net/article/2015-06-05/2824882/1

  8. Java中涉及到金额业务的处理

    一.MySql数据库中如何定义关于金额字段: 建议定义成[DECIMAL]类型,而不是float或者是double,因为这个两者是以二进制储存的,存在一定的误差.具体事例可参考https://blog ...

  9. js动态检测加载 JQ

    var jqcdnurl = 'https://cdn.bootcss.com/jquery/3.2.1/jquery.js'; //控制台输出 function log() { for (var i ...

  10. ActiveMQ异步分发消息

    org.apache.activemq.ActiveMQConnection 类中有个参数: protected boolean dispatchAsync=true; 这个参数的含义到底是什么? 使 ...