您的位置:首页 > 其它

shiro身份验证入门结合shiro的MD5加密技术自定义Realm-简单Demo

2017-06-30 14:53 435 查看
这个Demo,只是一个简单的shiro身份验证部分,不涉及到授权部分。算是shiro入门。

具体的shiro介绍就不说了,官网和草根们在网上都分享了很多,原理自己去看吧。这里直接写代码了。

第一:准备jar包

shiro-core-1.2.3.jar(shiro主要jar,其他jar根据情况自己添加)

log4j-1.2.17.jar

slf4j-api-1.7.5.jar

junit-4.9.jar

commons-logging-1.1.1.jar

第二:进行身份验证,首先我们要明确几个东西

1、subject,代表了当前“用户”。普通用户,或者其他系统等等。

2、secrityManager,安全管理器,进行授权和认证

3、Token[用户名,密码/证书]  ,里面放着用户信息。

4、realm(接口),为认证授权提供数据。可自定义,继承AuthorizingRealm类,或实现Realm接口

5、.ini文件配置。类似Ioc容器,系统可以读取ini文件,底层利用反射机制,setter注入(有点深奥,说不明白)

第三:开始准备上面提到的东西。

1、准备suject:

新建一个测试类,写一个测试方法

public class TestLoginShiro {
@Test
public void login() {
//获取工厂,加载.ini文件初始化工厂,后面有ini文件的配置说明
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
   //得到securityManager实例
SecurityManager securityManager = factory.getInstance();
  //绑定SecurityUtils
SecurityUtils.setSecurityManager(securityManager);
   //得到subject
   Subject subject = SecurityUtils.getSubject();
   //获得token,把用户名,密码放里面,这个用户名和密码是页面或其他请求传来的
   UsernamePasswordToken token = new UsernamePasswordToken("zhang","123");
  try{
    subject.login(token);//4、登录,即身份验证
      } catch(AuthenticationException e){
    System.out.println("error");//5、身份验证失败
      }
  

    boolean authenticated = subject.isAuthenticated();//登录状态

    System.out.println("是否成功登录:"+authenticated);   
    subject.logout();//6、退出
   }
}

2、自定义realm类:继承AuthorizingRealm类,或实现Realm接口

先看 实现Realm的操作:新建一个类MyRealm1

public class MyRealm1 implements Realm{

@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {

                //从token中获取用户名和密码
String username = (String)token.getPrincipal();
String password =new String( (char[])token.getCredentials());

               //在实际开发中下面的zhang和123都是从Service层查找出来的再做相应判断
if(!"zhang".equals(username)){
System.out.println("username is  error");
throw new UnknownAccountException("用户名错误");
}
if(!"123".equals(password)){
throw new IncorrectCredentialsException("密码错误");
}
System.out.println("ok");

                //返回AuthenticationInfo 的实现类SimpleAuthenticationInfo,里面装载了用户名密码和realm类,为以后授权做准备
return new SimpleAuthenticationInfo(username,password,getName());
}
@Override

       //获得当前类名
public String getName() {
return "myrealm1";
}
@Override

       //判断token类型是否符合
public boolean supports(AuthenticationToken token) {      
return token instanceof UsernamePasswordToken;
}

}

3、配置shiro-reaml.ini文件(名字随意),它是连通realm和subject关键。

新建shiro-reaml.ini文件,位置随意,我放在src根目录下了,设置文件打开方式在文件上右键 openWith-->Text Editor。(不设置可能读取不到)

文件内容:

[main]

myRealm1=test1.MyRealm1

securityManager.realms=$myRealm1

现在就可以用junit测试了。以上便完成了一个简单的登录验证。

下面说一下通过继承AuthorizingRealm类的操作,同时加上哈希散列MD5加盐(salt)加密技术。

1、准备suject--(同上不变)

2、写一个简单地工具类MD5Util(shiro自带MD5加密包)

      当用户注册时可以通过MD5对密码加密后存入数据库,数据库表中为密码为密文,盐为明文。

      当用户登录时获取数据库中的数据密码(密文)和盐(明文),通过shiro自带解密方法,

      解密后和用户传过来的密码进行对比

import org.apache.shiro.crypto.hash.Md5Hash;

public class MD5Util {

        //pwd为明文密码,salt为盐(可自定义),i加密次数
public static String toMd5(String pwd,String salt,int i){

Md5Hash toMd5 = new Md5Hash(pwd,salt,i);
return toMd5.toString();
}

}

这里这个工具类暂时不用,一般是注册时使用。不过要了解其原理。

3、新建MyRealm1继承AuthorizingRealm类

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.authz.AuthorizationInfo;

import org.apache.shiro.realm.AuthorizingRealm;

import org.apache.shiro.realm.Realm;

import org.apache.shiro.subject.PrincipalCollection;

import org.apache.shiro.util.ByteSource;

public class MyRealm1 extends AuthorizingRealm{

@Override
//这个方法是给授权准备的,暂时不用
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//获取token里的用户名
String username = (String)token.getPrincipal();
if(!"zhang".equals(username)){
System.out.println("username is  error");
throw new UnknownAccountException("用户名错误");
}
//这里应该是调用service层从数据库中查询出的密码(密文)和盐(明文)
String password="e99a18c428cb38d5f260853678922e03";//123abc通过一次加密的结果

String salt="abc";
//传入用户名密码盐和类名,自动解析出密码和token中的进行对比
return new SimpleAuthenticationInfo(username,password,ByteSource.Util.bytes(salt),getName());
}

4、配置shiro-reaml.ini文件,加密次数注册和登录配置要一致

[main]

#定义哈希散列类

credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher

#告知用的是MD5加密技术

credentialsMatcher.hashAlgorithmName=md5

#告知加密迭代几次,这里是1次

credentialsMatcher.hashIterations=1

#定义realm

myRealm1=test1.MyRealm1

#设置realm的credentialsMatcher属性

myRealm1.credentialsMatcher=$credentialsMatcher

#指定realm为myRealm1

securityManager.realms=$myRealm1

至此,可以测试了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: