shiro安全框架
shiro是Apache提供的安全框架,主要有四大功能:认证(即登录认证)、授权(授权用户拥有访问哪些资源权限)、回话管理(管理用户的session)以及加密(数据加密)。
首先创建一个javase或者javaee项目,我是建立的javaee项目,首先创建一个简单的shiro项目。
一、shiro认证
在src下创建一个名为shiro.ini的文件,文件内容写入:
[users]
zhangsan=123456
[users]表示是用户组,zhangsan是用户名,123456是密码,只是简单的连接,就不需要直接从数据库获取了,随后会讲从如何使用shiro连接数据库实现认证。
导入架包:
写一个测试代码实现基本的认证:
package com.yjb.text;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.util.Factory;
import com.yjb.shiroutis.ShiroSubject;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
public class Text {
public static void main(String[] args) {
//获取SecurityManager工厂对象
Factory<SecurityManager> foctory=new IniSecurityManagerFactory("classpath:shiro.ini");
//获取SecurityManager实例对象
SecurityManager securityManager=foctory.getInstance();
//将SecurityManager实例兑现设置到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//获取subject实体
Subject subject=SecurityUtils.getSubject();
//获取token,用于与shiro文件数据进行比对
UsernamePasswordToken token=new UsernamePasswordToken("zhangsan", "123456");
//shiro登录,
subject.login(token);
if(subject.isAuthenticated()){//isAuthenticated()的返回值为true表示比对成功
System.out.println("登录成功");
}else{
System.out.println("失败");
}
}
}
注意事项:
第一点:
在获取SecurityManager工厂对象会报错,这里会报错
new IniSecurityManagerFactory("classpath:shiro.ini");
原因是Apache有一个SecurityManager对象,而java.lang也有一个,所以需要手动导包为import org.apache.shiro.mgt.SecurityManager;或者直接点击错误使用静态导入。
第二点:报错问题
将shiro的配置文件配置为如下:
[users]
张三=123456
然后在获取token处改为
UsernamePasswordToken token=new UsernamePasswordToken("张三", "123456");
运行会报错
log4j:WARN No appenders could be found for logger (org.apache.shiro.io.ResourceUtils).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.apache.shiro.authc.UnknownAccountException: Realm [org.apache.shiro.realm.text.IniRealm@7b6bb7b1] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - 张三, rememberMe=false].
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:184)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
at com.yjb.text.Text.main(Text.java:26)
原因是配置文件不允许出现中文,往后与ssm框架整合的时候,shiro的配置文件可以改为shiro.xml。现在还不能改。
第三点:出现异常信息
Exception in thread "main" java.lang.IllegalArgumentException: Line argument must contain a key and a value. Only one string token was found.
at org.apache.shiro.config.Ini$Section.splitKeyValue(Ini.java:551)
at org.apache.shiro.config.Ini$Section.toMapProps(Ini.java:576)
at org.apache.shiro.config.Ini$Section.<init>(Ini.java:473)
at org.apache.shiro.config.Ini$Section.<init>(Ini.java:454)
at org.apache.shiro.config.Ini.addSection(Ini.java:311)
at org.apache.shiro.config.Ini.load(Ini.java:360)
at org.apache.shiro.config.Ini.load(Ini.java:296)
at org.apache.shiro.config.Ini.load(Ini.java:284)
at org.apache.shiro.config.Ini.loadFromPath(Ini.java:253)
at org.apache.shiro.config.Ini.fromResourcePath(Ini.java:234)
原因是存贮在本地没有存贮为NASI格式,需要统一格式,我的项目格式是utf-8,首先需要在Windows中修改项目空间为utf-8
然后删除shiro.ini文件,重新创建一个,保存到本地是,会变成NASI编码。如果还不行,直接到本地改编码。
第四点:出现错误信息
Exception in thread "main" org.apache.shiro.authc.UnknownAccountException: Realm [org.apache.shiro.realm.text.IniRealm@5ce904c4] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - 12, rememberMe=false].
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:184)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
at com.yjb.text.Text.main(Text.java:26)
和错误信息:
log4j:WARN No appenders could be found for logger (org.apache.shiro.io.ResourceUtils).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - zhangsan, rememberMe=false] did not match the expected credentials.
at org.apache.shiro.realm.AuthenticatingRealm.assertCredentialsMatch(AuthenticatingRealm.java:600)
at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:578)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
at com.yjb.text.Text.main(Text.java:27)
前者错误为用户名错误,后者为密码错误,需要处理异常:
package com.yjb.text;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.util.Factory;
import com.yjb.shiroutis.ShiroSubject;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
public class Text {
public static void main(String[] args) {
//获取SecurityManager工厂对象
Factory<SecurityManager> foctory=new IniSecurityManagerFactory("classpath:shiro.ini");
//获取SecurityManager实例对象
SecurityManager securityManager=foctory.getInstance();
//将SecurityManager实例兑现设置到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//获取subject实体
Subject subject=SecurityUtils.getSubject();
//获取token,用于与shiro文件数据进行比对
UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","12");
//shiro登录,
try {
subject.login(token);
if(subject.isAuthenticated()){//isAuthenticated()的返回值为true表示比对成功
System.out.println("登录成功");
}
} catch (IncorrectCredentialsException e) {
System.out.println("密码错误");
}catch (UnknownAccountException e) {
System.out.println("用户名错误错误");
}catch (Exception e) {
System.out.println("用户过期或者被禁用");
}
}
}
shiro中有很多异常类来处理异常,有用户错误,密码错误,用户过期,密码过期,用户被禁用等异常,主要处理前两个,其他的异常使用Exception 异常处理就够了。
错误类类型
UnknownAccountException:认证异常,即用户名不正确。
DisabledAccountException:账户失效异常。
IncorrectCredentialsException:凭证异常,即密码不正确。
ExpiredCredentialsException:凭证过期。
ExcessiveAttemptsException:尝试次数过多。
2、shiro配置文件讲解
shiro的ini文件有四个组,分别:
1,[main]组:用于配置程序的SecurityManager实例以及任何它的依赖组件。
2,[users]组:用于定义一组用户账户,可以包含用户名密码,甚至可以包含角色。
3,[roles]组:用于定义在[users]中的角色与权限关联起来。
[users]组合[roles]组相关关联实例:
[users]
zhangsan=123456,roles1
[roles]
roles1=user:add,user:delete
3:jdbcRealm
使用c3p0数据库连接池,使用jdbcRealm需要数据库的表名为users,需要有三个字段username,password和password_salt
shiro.ini配置文件
[main]
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysqql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/user
dataSource.user=root
dataSource.password=1232626yjb
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
securityManager.realm=$jdbcRealm
[users]
zhansan=12345
测试代码:
package com.yjb.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
public class Text {
public static void main(String[] args) {
Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager=factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token= new UsernamePasswordToken("lisi","11111");
try {
subject.login(token);
if(subject.isAuthenticated()){
System.out.println("成功");
}
} catch (AuthenticationException e) {
System.out.println(e);
}
}
}
4,认证策略
4.1,shiro提供了三种认证策略
AtLeastOneSuccessfulStrategy:只要有一个(或更多)的Realm验证成功,那么认证将被视为成功。
FirstSuccessfulStrategy:只要有一个Realm验证成功,整体认证将被视为成功,且后续Realm将被忽略。
AllSuccessfulStrategy:所有Realm成功,认证才视为成功。
默认认证策略是AtLeastOneSuccessfulStrategy。
4.2,实现认证策略
在securityManager中可以配置验证器,首先需要获取验证策略
在ini文件中配置
authcStrategy =org.apache.shiro.authc.pam.FirstSuccessfulStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy
5,自定义realm
在使用JdbcRealm时,已经规定了数据库中的表名和表字段规范,但是在日常开发中,表名和表字段为realm规定的名字。自定义realm就是为了解决这个问题的。
package com.yjb.shiro;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
public class UserRealm extends AuthorizingRealm {
@Override
/*授权*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
// TODO Auto-generated method stub
return null;
}
/*认证*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
/*username和password表示从数据库取出的数据
在封装到SimpleAuthenticationInfo类中,然后在配置文件中进行配置
*
*/
String username="zhansan";
String password="1111";
SimpleAuthenticationInfo info =new SimpleAuthenticationInfo(username,password,getName());
return info;
}
}
配置文件:
[main]
user=com.yjb.shiro.UserRealm
securityManager.realm=$user
二:加密
shiro提供了一系列加密算法,所在包为:org.apache.shiro.crypto.hash

浙公网安备 33010602011771号