shiro学习全记录

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"));

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 说明:本文很多观点和内容来自互联网以及各种资料,如果侵犯了您的权益,请及时联系我,我会删除相关内容。 权限管理 基...
    寇寇寇先森阅读 7,574评论 8 76
  • 前言 上一章主要对Shiro功能,运行原理,架构设计进行了介绍,这一章我们主要学习Shiro的身份验证。本章的代码...
    卑微幻想家阅读 2,051评论 0 12
  • 用口红可以提升人的气质,口红可以说是女性人手必备的,有的一支有的则是好几支,但是据报告显示女性朋友一生平均吃掉1....
    树静风止123阅读 97评论 0 0
  • 随着农业机械化的发展和普及,极大地提高了劳动效率,解放了农业的生产力。一些传统的劳动方式也就自然而然地退出了农村农...
    泰山寒梅阅读 1,566评论 25 20
  • 在乡下的日子 有隔壁慈祥的老奶奶 有小玩伴一起读书玩耍 下雨天 递伞给淋湿的龙猫 童话总是那么美好 拥有一颗童心 ...
    非鱼值乐阅读 135评论 0 1