shiro学习笔记(四) ini配置以及加解密

时间:2022-05-05 09:22:51

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学习笔记四&lpar;Shiro集成WEB&rpar;

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

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

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

  3. kvm虚拟化学习笔记&lpar;四&rpar;之kvm虚拟机日常管理与配置

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

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

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

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

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

  6. shiro学习笔记&lowbar;0600&lowbar;自定义realm实现授权

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

  7. go微服务框架kratos学习笔记五&lpar;kratos 配置中心 paladin config sdk &lbrack;断剑重铸之日,骑士归来之时&rsqb;&rpar;

    目录 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. 学习笔记&lowbar;J2EE&lowbar;SpringMVC&lowbar;03&lowbar;注解配置&lowbar;&commat;RequestMapping用法

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

随机推荐

  1. 公钥私钥和RSA算法

    1, RSA算法原理(一) http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html 2, RSA算法原理(二) http: ...

  2. webpack初学

    写在前面的话 阅读本文之前,先看下面这个webpack的配置文件,如果每一项你都懂,那本文能带给你的收获也许就比较有限,你可以快速浏览或直接跳过:如果你和十天前的我一样,对很多选项存在着疑惑,那花一段 ...

  3. 3-附1 -&gt&semi;和&ast;的区别

    问题: c++ .和 ->有什么区别? 还有什么是继承什么是派生?-------------------------------------------------------------- 比 ...

  4. &lbrack;Papers&rsqb;NSE&comma; &dollar;u&lowbar;3&dollar;&comma; Lebesgue space &lbrack;Kukavica-Ziane&comma; Nonlinearity&comma; 2006&rsqb;

    $$\bex u_3\in L^p(0,T;L^q(\bbR^3)),\quad \frac{2}{p}+\frac{3}{q}=\frac{5}{8},\quad \frac{24}{5}<q ...

  5. 在oracle表中增加字段,并调整字段的顺序

    增加字段的语句很简单,以用户身份连接oracle服务: alter table tablename add(colname coltype); # 填上表名.字段名.字段类型 修改字段顺序前,查看表中 ...

  6. 蓝牙协议分析&lpar;9&rpar;&lowbar;BLE安全机制之LL Privacy

    1. 前言 在上一篇文章[1]中,我们介绍了BLE的白名单机制,这是一种通过地址进行简单的访问控制的安全机制.同时我们也提到了,这种安全机制只防君子,不防小人,试想这样一种场景: A设备表示只信任B. ...

  7. Golang并发编程优势与核心goroutine及注意细节

    Go语言为并发编程而内置的上层API基于CSP(communication sequential processes,顺序通信进程)模型.这就意味着显式锁都是可以避免的,比如资源竞争,比如多个进程同时 ...

  8. Alpha冲刺3

    前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/9971198.html 作业博客:https://edu.cnblogs.com/campus/ ...

  9. oracle数据库使用小结

    select * from r_patient a where a.birthdate= to_date('1953-03-01','yyyy-mm-dd');select * from r_pati ...

  10. www&period;verycd&period;com

    #encoding=utf-8 import urllib import urllib2 postdate = urllib.urlencode({'continueURL':'http://www. ...