shiro的入门级使用(纯java应用)

1. 创建一个新的java应用(maven)

在pom文件中引入如下依赖:

<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-core</artifactId>
  <version>1.4.0</version>
</dependency>

<!-- 日志工具 -->
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.2</version>
</dependency>

<!--  shiro默认需要的日志工具,不添加时shiro运行失败 -->
<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.2</version>
</dependency>

工程结构如下图:
shiro的入门级使用(纯java应用)

2. 通过配置文件的方式使用shiro

(1)在resources文件夹下新增TestShiro.ini配置文件,内容如下:

#[main]
myRealm = com.ynsh.security.shiro.DatabaseRealm    
credentialsMatcher = com.ynsh.security.shiro.MyCredentialsMatcher    
myRealm.credentialsMatcher = $credentialsMatcher
securityManager.realms = $myRealm
securityManager.sessionManager.globalSessionTimeout = 1800000

[users]
javass = cc,role1    

[roles]
role1 = p1,p2

(2)创建自定义的realm

package com.ynsh.security.shiro;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.HashSet;
import java.util.Set;

public class DatabaseRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        String userName = (String)getAvailablePrincipal(principalCollection);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> s = new HashSet<>();
        s.add("p1");
        info.setStringPermissions(s); //赋予权限p1

        Set<String> r = new HashSet<>();
        r.add("role1");    //赋予角色role1
        info.setRoles(r);

        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;

        String userName = (String)upToken.getPrincipal();
//        if ("javass".equals(userName)) throw new AuthenticationException("javass用户禁止登录"); 如果想禁止某一个用户登录,可以在这里操作:判断到是这个用户时,扔出异常

        //这个密码正常情况下应该是从数据库去获取
        String passWord = "428729c9b80aa3198300caabb24f8a88";
        
        //扔给credentialsMatcher去判断
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                userName, passWord, null, this.getName());

        return simpleAuthenticationInfo;
    }
    //父类调用完doGetAuthenticationInfo会调用assertCredentialsMatch,判断密码是否相符
}

(3)创建自定义的credentialsMatcher,即密码验证器

package com.ynsh.security.shiro;

import com.ynsh.security.utils.Md5Util;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;

public class MyCredentialsMatcher extends SimpleCredentialsMatcher {

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken uToken = (UsernamePasswordToken)token;
        String inPassword = new String(uToken.getPassword()); //这个密码是客户提交的密码,即下面main函数中用new UsernamePasswordToken("javass","bb")提交的“bb”
        //这个密码是上面realm中给出的数据库密码,也就是正确的密码:String passWord = "428729c9b80aa3198300caabb24f8a88"
        String dbPassword = (String)info.getCredentials();

        String encryptInPassword = Md5Util.encrypt(inPassword);
        return encryptInPassword.equals(dbPassword);
    }

}

(4)上面用到了一个自定义的md5Util组件:

package com.ynsh.security.utils;

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

public class Md5Util {

    public static String encrypt(String originalString){
        //盐
        String salt = "salt";
        //散列次数
        int hashIterations = 2;
        Md5Hash md5Hash = new Md5Hash(originalString, salt, hashIterations);

        String password_md5 =  md5Hash.toString();
        System.out.println(password_md5);
        //第一个参数:散列算法
        SimpleHash simpleHash = new SimpleHash("md5", originalString, salt, hashIterations);
        System.out.println(simpleHash.toString());

        return simpleHash.toString();
    }

}

(5)正式开始验证,写main函数:

package com.ynsh;

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.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App 
{
    private static final Logger logger = LoggerFactory.getLogger(App.class);
    public static void main( String[] args )
    {

        Factory<SecurityManager> f = new IniSecurityManagerFactory("classpath:TestShiro.ini");
        SecurityManager s = f.getInstance();
        SecurityUtils.setSecurityManager(s);

        UsernamePasswordToken token = new UsernamePasswordToken("javass","bb");
        token.setRememberMe(true);

        Subject currentUser = SecurityUtils.getSubject();
        try {
            currentUser.login(token);
        }catch (Exception e){
            logger.error(e.getMessage());
            e.printStackTrace();
        }

//        boolean flag = currentUser.isPermitted("p1");
        boolean flag = currentUser.isAuthenticated();
        System.out.println("flag == "+flag);

        flag = currentUser.hasRole("role1");
        logger.info("用户有角色:{}",flag);

    }
}

(6)运行结果如下:

[INFO ] 2018-11-22 15:13:43,087 method:org.apache.shiro.config.IniSecurityManagerFactory.isAutoApplyRealms(IniSecurityManagerFactory.java:127)
Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur.
428729c9b80aa3198300caabb24f8a88
428729c9b80aa3198300caabb24f8a88
[INFO ] 2018-11-22 15:13:43,102 method:org.apache.shiro.session.mgt.AbstractValidatingSessionManager.enableSessionValidation(AbstractValidatingSessionManager.java:233)
Enabling session validation scheduler...
flag == true
[INFO ] 2018-11-22 15:13:43,147 method:com.ynsh.App.main(App.java:43)
用户有角色:true

Process finished with exit code 0

后记

TestShiro.ini中配置了[users]和[roles]其实是不起作用的,这个配置是一开始的时候为了验证shiro默认的iniRealm的时候使用的。
因为自定义了realm,可以将[users]和[roles]的内容全部删除。

相关推荐