Shiro

shiro学习全记录

2018-04-18  本文已影响49人  XuJiaxin_

1.shiro整体架构

image.png

1.Authenticator=>认证器:负责用户登录登出
2.Authoorizer=>授权器:shiro给用户授权
3.Session Manager=>Session管理机制
4.SessionDao=>负责增删改查
5.Pluggable Realms=>与数据库交互,获取权限信息
6.Cryptography=>加密

2.Shiro认证

image.png

1.创建模版:


image.png

1.pom.xml添加依赖

<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
        </dependency>

2.创建测试类


image.png
package com.imooc.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Before;
import org.junit.Test;

/**
 * Created by fly on 2018/4/18.
 */
public class AuthenticationTest {

    //暂时使用SimpleAccountRealm
    SimpleAccountRealm simpleAccountRealm=new SimpleAccountRealm();

    //创建一个用户
    @Before
    public void addUser(){
        simpleAccountRealm.addAccount("Mark","123456");
    }

    @Test
    public void testAuthentication(){

        //1.构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
        defaultSecurityManager.setRealm(simpleAccountRealm);

        //2.主体提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject=SecurityUtils.getSubject();//注意使用shiro下的Subject

        UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
        subject.login(token);

        System.out.println("isAuthenticated:"+subject.isAuthenticated());

        subject.logout();

        System.out.println("isAuthenticated:"+subject.isAuthenticated());
    }

}

认证结果:


image.png

2.Shiro授权

image.png

1.给用户赋予一个角色


image.png

2.验证是否拥有该角色


image.png
结果:
image.png

若主体角色错误(异常)


image.png
扩展
可同时添加多个角色,check多个角色
image.png

Shiro自定义Realm

内置Realm:
1.IniRealm
2.JdbcRealm

1.IniRealm测试类

目录结构


image.png

创建IniRealmTest

package com.imooc.test;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

/**
 * Created by fly on 2018/4/18.
 */
public class IniRealTest {

    //创建IniRealm
    IniRealm iniRealm=new IniRealm("classpath:user.ini");

    @Test
    public void testAuthentication(){

        //1.构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
        defaultSecurityManager.setRealm(iniRealm);

        //2.主体提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject=SecurityUtils.getSubject();//注意使用shiro下的Subject

        UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
        subject.login(token);

        System.out.println("isAuthenticated:"+subject.isAuthenticated());
        //权限验证
        subject.checkRole("admin");
        //是否具备某权限
        subject.checkPermission("user:delete");
    }
}

创建user.ini

[users]
Mark=123456,admin
[roles]
admin=user:delete

运行结果


image.png

2.JdbcRealm

在pom.xml中导入mysql支持和datasource数据源

 <!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.36</version>
        </dependency>
        <!--数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>
    </dependencies>

JdbcRealmTest类

package com.imooc.test;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

/**
 * Created by fly on 2018/4/19.
 */
public class JdbcRealmTest {


    //创建jdbc数据源
    DruidDataSource dataSource=new DruidDataSource();

    //设置jdbc入口
    {
        dataSource.setUrl("jdbc:mysql://localhost:3306/shiro_test");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
    }

    @Test
    public void testAuthentication(){

        //创建JdbcRealm
        JdbcRealm jdbcRealm=new JdbcRealm();
        //设置JdbcRealm数据源
        jdbcRealm.setDataSource(dataSource);
        //设置权限开关(默认为false)
        jdbcRealm.setPermissionsLookupEnabled(true);

        //1.构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
        defaultSecurityManager.setRealm(jdbcRealm);

        //2.主体提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject=SecurityUtils.getSubject();//注意使用shiro下的Subject

        UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","123456");
        subject.login(token);

        System.out.println("isAuthenticated:"+subject.isAuthenticated());

        //验证角色
        subject.checkRole("admin");
        //验证权限
        subject.checkPermission("user:delete");

    }
}

如果使用shiro默认的查询语句,就根据shiro查询语句创建表


image.png
image.png

注意:如果不设置开关 subject.checkPermission("user:delete");将报错

image.png
image.png

自定义sql语句查询


image.png

3.自定义Realm

创建自定义CustomRealm和测试类CustomRealmTest


image.png

没有从数据库查询,使用Map和Set进行模拟查询

CustomRealm

package com.imooc.realm;

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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Created by fly on 2018/4/19.
 */
public class CustomRealm extends AuthorizingRealm {

    Map<String,String> userMap=new HashMap<String, String>(16);
    {
        userMap.put("Mark","123456");
        super.setName("customRealm");
    }

    //授权方法
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String userName=(String) principalCollection.getPrimaryPrincipal();
        //从数据库或者缓存中获取角色数据
        Set<String> roles=getRolesByUserName(userName);
        //从数据库或者缓存中获取权限数据
        Set<String> permissions=getPermissionsByUserName(userName);

        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setStringPermissions(permissions);
        simpleAuthorizationInfo.setRoles(roles);

        return simpleAuthorizationInfo;
    }

    //模拟数据库获取角色数据
    private Set<String> getPermissionsByUserName(String userName) {
        Set<String> sets=new HashSet<String>();
        sets.add("user:delete");
        sets.add("user:select");
        return sets;
    }

    //模拟数据库获取角色数据
    private Set<String> getRolesByUserName(String userName) {
        Set<String> sets=new HashSet<String>();
        sets.add("admin");
        sets.add("user");
        return sets;
    }

    //认证方法
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.从主体穿过来的认证信息中,获得用户名
        String userName=(String) authenticationToken.getPrincipal();

        //2.通过用户名到数据库中获取凭证
        String password=getPasswordByUserName(userName);
        if(password==null){
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo("Mark",password,"customRealm");

        return authenticationInfo;
    }

    //模拟数据库查询
    private String getPasswordByUserName(String userName) {

        return userMap.get(userName);
    }
}

CustomRealmTest

package com.imooc.test;

import com.imooc.realm.CustomRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;

/**
 * Created by fly on 2018/4/19.
 */
public class CustomReamlTest {

    @Test
    public void testAuthentication(){

        //创建CustomRealm
        CustomRealm customRealm=new CustomRealm();

        //1.构建SecurityManager环境
        DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
        defaultSecurityManager.setRealm(customRealm);

        //2.主体提交认证请求
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject=SecurityUtils.getSubject();//注意使用shiro下的Subject

        UsernamePasswordToken token=new UsernamePasswordToken("Mark","123456");
        subject.login(token);

        System.out.println("isAuthenticated:"+subject.isAuthenticated());

        subject.checkRole("admin");
        subject.checkPermissions("user:delete","user:select");
    }
}

Shiro加密

1.Shiro散列配置

HashedCredentialsMatcher
自定义Realm中使用散列
盐的使用

在验证方法中设置加密类型,加密次数

HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");//设置加密方法
        matcher.setHashIterations(1);//设置加密次数
        customRealm.setCredentialsMatcher(matcher);

在Realm中设置盐等参数

 //设置盐
        authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("Mark"));

============未完待续=================

上一篇下一篇

猜你喜欢

热点阅读