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: this & Object Prototypes( 第2章 this)

    this is a binding made for each function invocation, based entirely on its call-site (how the functi ...

  2. codeforces668b //Little Artem and Dance// Codeforces Round #348

    题意:2种操作,转动或者奇偶位互换. 不论怎么交换,1的后两位一定是3,3的后两位一定是5.因此只要记录1,2的位置. //#pragma comment(linker,"/STACK:10 ...

  3. 小程序模板中data传值有无...

    A:<template is="gemSelectColor" data="{{optionData}}" />B:<template is= ...

  4. Linux中磁盘分区——理论篇

    Linux中磁盘分区——理论篇 现在主流的分区的方式有两种——MBR分区和GPT分区,本文将着重介绍MBR分区底层原理,及用相关命令验证相关原理 Linux中磁盘分区理论篇 为什么要对磁盘进行分区 M ...

  5. file 文件上传后缀转化小写

    1.上传的文件后缀是大写的我们做上传文件的时候考虑的比较少,所以我就想把客户上传的文件后缀统一一下,后面我解析附件的时候比较好解析.例子:我得到的文件名称:$infoFileName;$fileNam ...

  6. MySQL共享表空间概念

    1.表空间概念 Innodb存储引擎可将所有数据存放于ibdata*的共享表空间,也可将每张表存放于独立的.ibd文件的独立表空间.共享表空间以及独立表空间都是针对数据的存储方式而言的. 共享表空间 ...

  7. Maven插件系列之spring-boot-maven-plugin

    Spring Boot的Maven插件(Spring Boot Maven plugin)能够以Maven的方式为应用提供Spring Boot的支持,即为Spring Boot应用提供了执行Mave ...

  8. py requests.get

    import osimport requestsimport jsonfrom Util import Propertiesprint('########[公务员自助列表]############## ...

  9. std::string find 的返回值

    std::string  的方法 find,返回值类型是std::string::size_type, 对应的是查找对象在字符串中的位置(从0开始), 如果未查找到,该返回值是一个很大的数据(4294 ...

  10. laravel模型关联:

    一对一hasOne(用户-手机号) 一对多has Many(文章-评论) 一对多反向belongsTo(评论-文章) 多对多belongsToMany(用户-角色) 远层一对多hasManyThrou ...