Shiro学习第一式身份验证2

开心一下:昨天晚上下班回家,一民警迎面巡逻而来。突然对我大喊:站住!

民警:javaint类型占几个字节?

我:4个。

民警:你可以走了。

我感到很诧异。

我:为什么问这样的问题?

民警:深夜还在街上走,寒酸苦逼的样子,不是小偷就是程序员。

 

继续学习开涛的Shiro身份验证,介绍一下开发工具和开发环境,jdk1.6.0_43+Tomcat6.0.29+ MyEclipse10.5,没有使用Maven

Realm

Realm:域,Shiro从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。如我们之前的ini配置方式将使用org.apache.shiro.realm.text.IniRealm。新建web工程,工程名为ShrRealm,选择Java EE5.0

单Realm配置

一、 新建java类MyRealm1.java

package com.zsf.realms;

 

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authc.IncorrectCredentialsException;

import org.apache.shiro.authc.SimpleAuthenticationInfo;

import org.apache.shiro.authc.UnknownAccountException;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.realm.Realm;

 

public class MyRealm1 implements Realm {

 

public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)

throws AuthenticationException {

System.out.println("MyRealm1~~~~~~~~~~~~~~~~~~~~~~~~~~");

//得到用户名

String username = (String) token.getPrincipal();

//得到密码

String password = new String((char[])token.getCredentials()); 

if(!"zhang".equals(username)) {

throw new UnknownAccountException();//用户名错误

}

if(!"1234".equals(password)) {

throw new IncorrectCredentialsException();//密码错误

}

//如果身份验证成功,返回一个AuthenticationInfo实现;

return new SimpleAuthenticationInfo(username, password, getName());

}

 

public String getName() {

return "MyRealm1";

}

 

public boolean supports(AuthenticationToken arg0) {

//仅支持UsernamePasswordToken类型的Token

return arg0 instanceof UsernamePasswordToken;

}

 

}

二、 在src下新建shiro-realm.in文件

#声明一个realm

myRealm1=com.zsf.realms.MyRealm1

#指定securityManagerrealms实现

securityManager.realms=$myRealm1

 

 

三、 新建类RealmTest.java

package com.zsf.test;

 

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.mgt.SecurityManager;

import org.apache.shiro.subject.Subject;

import org.apache.shiro.util.Factory;

 

/**

 * 类名: RealmTest.java

 * 作者张述飞

 * 创建时间: 2016-2-25上午10:26:58

 * 版本: V1.0

 * 功能描述:

 */

public class RealmTest {

public static void main(String[] args) {

//获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager

Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");

//得到SecurityManager实例,并绑定给SecurityUtils

SecurityManager securityManager = factory.getInstance();

SecurityUtils.setSecurityManager(securityManager);

//得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)

Subject subject = SecurityUtils.getSubject();

UsernamePasswordToken token = new UsernamePasswordToken("zhang", "1234");

try {

//登录,即身份验证

subject.login(token);

boolean flag = subject.isAuthenticated();

System.out.println("flag==="+flag);

System.out.println("登陆成功!");

} catch (AuthenticationException e) {

//身份验证失败

e.printStackTrace();

System.out.println("登陆失败!");

}

//6、退出

subject.logout();

}

 

}

四、 需导入的jar包

commons-beanutils-1.8.0.jar

commons-dbcp-1.2.1.jar

commons-logging-1.1.3.jar

commons-pool-1.3.jar

jtds-1.2.5.jar

shiro-core-1.2.4.jar

slf4j-api-1.7.9.jar

slf4j-jdk14-1.7.9.jar

五、 测试

运行RealmTest.java,

控制台会显示

MyRealm1~~~~~~~~~~~~~~~~~~~~~~~~~~

2016-2-25 10:29:04 org.apache.shiro.session.mgt.AbstractValidatingSessionManager enableSessionValidation

信息: Enabling session validation scheduler...

flag===true

登陆成功!

多Realm配置

六、 新建MyRealm2.java

package com.zsf.realms;

 

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authc.IncorrectCredentialsException;

import org.apache.shiro.authc.SimpleAuthenticationInfo;

import org.apache.shiro.authc.UnknownAccountException;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.realm.Realm;

 

public class MyRealm2 implements Realm {

 

public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)

throws AuthenticationException {

System.out.println("MyRealm2~~~~~~~~~~~~~~~~~~~~~~~~~~");

//得到用户名

String username = (String) token.getPrincipal();

//得到密码

String password = new String((char[])token.getCredentials()); 

if(!"wang".equals(username)) {

throw new UnknownAccountException();//用户名错误

}

if(!"123".equals(password)) {

throw new IncorrectCredentialsException();//密码错误

}

//如果身份验证成功,返回一个AuthenticationInfo实现;

return new SimpleAuthenticationInfo(username, password, getName());

}

 

public String getName() {

return "MyRealm2";

}

 

public boolean supports(AuthenticationToken arg0) {

//仅支持UsernamePasswordToken类型的Token

return arg0 instanceof UsernamePasswordToken;

}

 

}

七、 新建shiro-multi-realm.ini

#声明一个realm

myRealm1=com.zsf.realms.MyRealm1

myRealm2=com.zsf.realms.MyRealm2

#指定securityManagerrealms实现

securityManager.realms=$myRealm1,$myRealm2

 

八、 新建测试类MultiRealmTest.java

package com.zsf.test;

 

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.mgt.SecurityManager;

import org.apache.shiro.subject.Subject;

import org.apache.shiro.util.Factory;

 

/**

 * 类名: MultiRealmTest.java

 * 作者: 张述飞

 * 创建时间: 2016-2-25上午10:27:29

 * 版本: V1.0

 * 功能描述:

 */

public class MultiRealmTest {

public static void main(String[] args) {

//获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager

Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-multi-realm.ini");

//得到SecurityManager实例,并绑定给SecurityUtils

SecurityManager securityManager = factory.getInstance();

SecurityUtils.setSecurityManager(securityManager);

//得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)

Subject subject = SecurityUtils.getSubject();

UsernamePasswordToken token = new UsernamePasswordToken("wang", "123");

try {

//登录,即身份验证

subject.login(token);

boolean flag = subject.isAuthenticated();

System.out.println("flag==="+flag);

System.out.println("登陆成功!");

} catch (AuthenticationException e) {

//身份验证失败

e.printStackTrace();

System.out.println("登陆失败!");

}

//6、退出

subject.logout();

}

 

}

九、 测试

运行MultiRealmTest.java,

控制台会显示

MyRealm1~~~~~~~~~~~~~~~~~~~~~~~~~~

MyRealm2~~~~~~~~~~~~~~~~~~~~~~~~~~

2016-2-25 10:37:56 org.apache.shiro.session.mgt.AbstractValidatingSessionManager enableSessionValidation

信息: Enabling session validation scheduler...

flag===true

登陆成功!

JDBC Realm使用

十、 新建MyRealm3.java

package com.zsf.realms;

 

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authc.IncorrectCredentialsException;

import org.apache.shiro.authc.SimpleAuthenticationInfo;

import org.apache.shiro.authc.UnknownAccountException;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.realm.Realm;

 

public class MyRealm3 implements Realm {

 

public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)

throws AuthenticationException {

System.out.println("MyRealm3~~~~~~~~~~~~~~~~~~~~~~~~~~");

//得到用户名

String username = (String) token.getPrincipal();

//得到密码

String password = new String((char[])token.getCredentials()); 

if(!"zhang".equals(username)) {

throw new UnknownAccountException();//用户名错误

}

if(!"1234".equals(password)) {

throw new IncorrectCredentialsException();//密码错误

}

//如果身份验证成功,返回一个AuthenticationInfo实现;

return new SimpleAuthenticationInfo(username+"@163.com", password, getName());

}

 

public String getName() {

return "MyRealm3";

}

 

public boolean supports(AuthenticationToken arg0) {

//仅支持UsernamePasswordToken类型的Token

return arg0 instanceof UsernamePasswordToken;

}

 

}

十一、 新建shiro-jdbc-realm.ini

dataSource=org.apache.commons.dbcp.BasicDataSource

dataSource.driverClassName=net.sourceforge.jtds.jdbc.Driver

dataSource.url=jdbc:jtds:sqlserver://localhost:1433/TKERP

dataSource.username=sa

#dataSource.password=

jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm

jdbcRealm.dataSource=$dataSource

jdbcRealm.permissionsLookupEnabled = true

jdbcRealm.authenticationQuery = select Password from UserInfo where LoginName=?

securityManager.realms=$jdbcRealm

十二、 解析一下上面的ini文件

#dataSource.password=这句话表示数据库sa密码为空,必须要这么写,否则会报错

 

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:542)

at org.apache.shiro.config.Ini$Section.toMapProps(Ini.java:567)

at org.apache.shiro.config.Ini$Section.<init>(Ini.java:464)

at org.apache.shiro.config.Ini$Section.<init>(Ini.java:445)

at org.apache.shiro.config.Ini.addSection(Ini.java:302)

 

需要新建一个名为TKERP的数据库,还要新建一个表UserInfo,包括两个字段LoginName, Password,并且要填加一条记录,zsf,123

 

十三、 新建测试类JdbcRealmTest.java

package com.zsf.test;

 

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.mgt.SecurityManager;

import org.apache.shiro.subject.Subject;

import org.apache.shiro.util.Factory;

 

/**

 * 类名: JdbcRealmTest.java

 * 作者张述飞

 * 创建时间: 2016-2-25上午10:27:21

 * 版本: V1.0

 * 功能描述:

 */

public class JdbcRealmTest {

public static void main(String[] args) {

//获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager

Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");

//得到SecurityManager实例,并绑定给SecurityUtils

SecurityManager securityManager = factory.getInstance();

SecurityUtils.setSecurityManager(securityManager);

//得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)

Subject subject = SecurityUtils.getSubject();

UsernamePasswordToken token = new UsernamePasswordToken("zsf", "123");

try {

//登录,即身份验证

subject.login(token);

boolean flag = subject.isAuthenticated();

System.out.println("flag==="+flag);

System.out.println("登陆成功!");

} catch (AuthenticationException e) {

//身份验证失败

e.printStackTrace();

System.out.println("登陆失败!");

}

//6、退出

subject.logout();

}

 

}

十四、 测试

运行JdbcRealmTest.java,

控制台会显示

信息: Enabling session validation scheduler...

flag===true

登陆成功!

 

Authenticator及AuthenticationStrategy 

Authenticator的职责是验证用户帐号,是Shiro API中身份验证核心的入口点:

SecurityManager接口继承了Authenticator,另外还有一个ModularRealmAuthenticator实现,其委托给多个Realm进行验证,验证规则通过AuthenticationStrategy接口指定,默认提供的实现:

FirstSuccessfulStrategy:只要有一个Realm验证成功即可,只返回第一个Realm身份验证成功的认证信息,其他的忽略;

AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy不同,返回所有Realm身份验证成功的认证信息;

AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。

ModularRealmAuthenticator默认使用AtLeastOneSuccessfulStrategy策略。

假设我们有三个realm:

myRealm1: 用户名/密码为zhang/1234时成功,且返回身份/凭据为zhang/1234;

myRealm2: 用户名/密码为wang/123时成功,且返回身份/凭据为wang/123;

myRealm3: 用户名/密码为zhang/1234时成功,且返回身份/凭据为zhang@163.com/1234,和myRealm1不同的是返回时的身份变了;

 

 

十五、 新建shiro-authenticator-all-success.ini

#指定securityManagerauthenticator实现

authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator

securityManager.authenticator=$authenticator

 

#指定securityManager.authenticatorauthenticationStrategy实现

allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy

securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy

 

#声明一个realm

myRealm1=com.zsf.realms.MyRealm1

myRealm2=com.zsf.realms.MyRealm2

myRealm3=com.zsf.realms.MyRealm3

#指定securityManagerrealms实现

securityManager.realms=$myRealm1,$myRealm3

十六、 新建shiro-authenticator-all-fail.ini

#指定securityManagerauthenticator实现

authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator

securityManager.authenticator=$authenticator

 

#指定securityManager.authenticatorauthenticationStrategy实现

allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy

securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy

 

#声明一个realm

myRealm1=com.zsf.realms.MyRealm1

myRealm2=com.zsf.realms.MyRealm2

myRealm3=com.zsf.realms.MyRealm3

#指定securityManagerrealms实现

securityManager.realms=$myRealm1,$myRealm2

 

十七、 新建测试类AuthenticatorTest.java

package com.zsf.test;

 

import org.apache.shiro.SecurityUtils;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.config.IniSecurityManagerFactory;

import org.apache.shiro.mgt.SecurityManager;

import org.apache.shiro.subject.PrincipalCollection;

import org.apache.shiro.subject.Subject;

import org.apache.shiro.util.Factory;

 

/**

 * 类名: AuthenticatorTest.java

 * 作者张述飞

 * 创建时间: 2016-2-25上午10:27:12

 * 版本: V1.0

 * 功能描述:

 */

public class AuthenticatorTest {

public void login(String configFile) {

//获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager

Factory<SecurityManager> factory = new IniSecurityManagerFactory(configFile);

//得到SecurityManager实例,并绑定给SecurityUtils

SecurityManager securityManager = factory.getInstance();

SecurityUtils.setSecurityManager(securityManager);

//得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)

Subject subject = SecurityUtils.getSubject();

UsernamePasswordToken token = new UsernamePasswordToken("zhang""1234");

//登录,即身份验证

subject.login(token);

 

}

public void testAllSucessfulStrategyWithSuccess(){

System.out.println("调用成功方法~~~~~~~");

login("classpath:shiro-authenticator-all-success.ini");

Subject subject = SecurityUtils.getSubject();

PrincipalCollection principalCollection = subject.getPrincipals();

System.out.println("成功的集合:==="+principalCollection.asList().size());

}

public void testAllSucessfulStrategyWithSuccess(){

System.out.println("调用成功方法~~~~~~~");

login("classpath:shiro-authenticator-all-success.ini");

Subject subject = SecurityUtils.getSubject();

PrincipalCollection principalCollection = subject.getPrincipals();

System.out.println("成功的集合:==="+principalCollection.asList().size());

subject.logout();

}

public void testAllSucessfulStrategyWithFail(){

System.out.println("调用失败方法~~~~~~~");

login("classpath:shiro-authenticator-all-fail.ini");

Subject subject = SecurityUtils.getSubject();

PrincipalCollection principalCollection = subject.getPrincipals();

System.out.println("失败的集合:==="+principalCollection.asList().size());

subject.logout();

}

}

 

十八、 测试

运行RealmTest.java,

控制台会显示

调用成功方法~~~~~~~

2016-2-25 13:47:31 org.apache.shiro.config.IniSecurityManagerFactory isAutoApplyRealms

信息: Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.

MyRealm1~~~~~~~~~~~~~~~~~~~~~~~~~~

MyRealm3~~~~~~~~~~~~~~~~~~~~~~~~~~

2016-2-25 13:47:31 org.apache.shiro.session.mgt.AbstractValidatingSessionManager enableSessionValidation

信息: Enabling session validation scheduler...

2016-2-25 13:47:31 org.apache.shiro.config.IniSecurityManagerFactory isAutoApplyRealms

信息: Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.

成功的集合:===2

调用失败方法~~~~~~~

MyRealm1~~~~~~~~~~~~~~~~~~~~~~~~~~

MyRealm3~~~~~~~~~~~~~~~~~~~~~~~~~~

失败的集合:===2

 

这一章写的很乱,做完实例后都是直接上手抄的大神开涛的,本来想把自己理解的好好写一下,因为要出差,所以匆匆忙忙的写完了,需要源码的下!

 

重要事情说三遍,大神开涛的,大神开涛的,开涛的!

 

代码下载地址:

http://download.csdn.net/detail/zhangshufei8001/9443253

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值