美文网首页
Shiro安全框架学习记录

Shiro安全框架学习记录

作者: weisen | 来源:发表于2019-09-26 15:08 被阅读0次

参考来源

Shiro安全框架

一、Shiro认识和介绍

1、什么是Shiro
Apache的强大灵活的开源安全框架
认证、授权、企业会话管理、安全加密

2、Shiro与Spring Security比较

Shiro Spring Security
简单、灵活 复杂、笨重
可脱离Spring 不可脱离Spring
粒度较粗 粒度更细

3、Shiro整体架构

[图片上传失败...(image-d9c4de-1568169456216)]

二、Shiro认证授权过程

1、Shiro认证过程

graph LR
A(创建SecurityManager) -->B(主体提交认证)
B --> C(SecurityManager认证)
C --> D(Authenticator认证)
D --> E(Realm认证)

代码:

 SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
    @Before
    public void addUser(){
        simpleAccountRealm.addAccount("admin","admin123","admin","user");
    }

    @Test
    public void testAuthentication(){
        //创建SecurityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(simpleAccountRealm);
        //获取主体
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();
        //主体提交认证
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("admin", "admin123");
        subject.login(usernamePasswordToken);
        System.out.println("subject.isAuthenticated: "+subject.isAuthenticated());
        subject.logout();
        System.out.println("subject.isAuthenticated: "+subject.isAuthenticated());
    }

2、Shiro授权过程

graph LR
A(创建SecurityManager) -->B(主体授权)
B --> C(SecurityManager授权)
C --> D(Authorizer授权)
D --> E(Realm获取角色权限数据)

代码:

    subject.login(usernamePasswordToken);
    System.out.println("subject.isAuthenticated: "+subject.isAuthenticated());
    subject.checkRole("admin");
    subject.checkRoles("admin","user");

三、Shiro的Realm

1、Shiro的iniRealm使用

在Test Resources中添加文件user.ini,在里面添加用户信息

[users]
Admin=admin123,admin
Tom=tom123,system
[roles]
admin=user:delete
system=user:update

代码

 @Test
    public void testAuthentication(){
        IniRealm iniRealm = new IniRealm("classpath:user.ini");
        //创建SecurityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(iniRealm);
        //获取主体
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        //主体提交认证
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("Tom", "tom123");
        subject.login(usernamePasswordToken);
        System.out.println("subject.isAuthenticated: "+subject.isAuthenticated());
        subject.checkRole("system");
        subject.checkPermission("user:update");


    }

2、Shiro的JdbcRealm使用

代码:

 DruidDataSource datasource = new DruidDataSource();
    {
        datasource.setUrl("jdbc:mysql://192.168.243.20:9097/user_role");
        datasource.setUsername("root");
        datasource.setPassword("b#12345678");
    }
 @Test
    public void testAuthentication(){
        JdbcRealm jdbcRealm = new JdbcRealm();
        jdbcRealm.setDataSource(datasource);
        //创建SecurityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(jdbcRealm);

        //获取主体
      ...
    }    

因为JdbcRealm中会默认查询

DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";

所以在对应的库中添加users表,并带有相应字段和数据,则可查询成功

需要使用自定义的查询表时,可使用自定义的查询sql语句

String authSql = "select phone from aur_member where member_name = ?";
jdbcRealm.setAuthenticationQuery(authSql);
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("tim1", "13751836453");

3、Shiro自定义Realm

继承AuthorizingRealm类,doGetAuthorizationInfo是授权,doGetAuthenticationInfo是认证

public class CustomRealm extends AuthorizingRealm {
    Map<String,String> userMap = new HashMap<>();
    {
        userMap.put("admin","admin123");
        super.setName("customRealm");
    }


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String userName = (String) principalCollection.getPrimaryPrincipal();
        //从数据库或者缓存中获取角色数据
        Set<String> roles = getRolesByUserName(userName);
        Set<String> permissions = getPermissionByUserName(userName);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }

    private Set<String> getPermissionByUserName(String userName) {
        Set<String> sets = new HashSet<>();
        sets.add("user:delete");
        sets.add("user:add");
        sets.add("user:select");
        return sets;
    }

    private Set<String> getRolesByUserName(String userName) {
        Set<String> sets = new HashSet<>();
        sets.add("admin");
        sets.add("system");
        return sets;
    }

    @Override
    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("admin",password,"customRealm");
        return authenticationInfo;
    }

    // 模拟数据库
    private String getPasswordByUserName(String userName) {
       return userMap.get(userName);
    }
}

创建单元测试类

@Test
    public void testAuthentication(){
        CustomRealm customRealm = new CustomRealm();
        //创建SecurityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(customRealm);

        //获取主体
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        //主体提交认证
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("admin", "admin123");
        subject.login(usernamePasswordToken);
        System.out.println("subject.isAuthenticated: "+subject.isAuthenticated());
        subject.checkRole("admin");
        subject.checkPermissions("user:delete","user:select");
    }

四、Shiro加密

1、HashedCredentialsMatcher

在CustomRealmTest的testAuthentication方法中添加上

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

在数据库中保存的密码就需要MD5加密后的结果

public static void main(String[] args) {
    Md5Hash md5Hash = new Md5Hash("admin123");
    System.out.println(md5Hash.toString());
}

2、自定义Realm中使用散列

3、盐的使用

使用盐后的MD5值,将该值保存到数据库的表密码中

public static void main(String[] args) {
    Md5Hash md5Hash = new Md5Hash("admin123","admin");
    System.out.println(md5Hash.toString());
}

在CustomRealm的doGetAuthenticationInfo方法中添加上

authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("admin"));

相关文章

  • Shiro安全框架学习记录

    参考来源 Shiro安全框架 一、Shiro认识和介绍 1、什么是ShiroApache的强大灵活的开源安全框架认...

  • shiro RememeberMe 1.2.4反序列化漏洞

    Shiro简介:shiro(Java安全框架):apache shiro 是一个强大且易用的java安全框架框架,...

  • 权限框架Shiro学习之表结构设计

    权限框架Shiro学习之表结构设计 Shiro是一款优秀的开源安全框架,学习Shiro大家可以参考张开涛老师的博客...

  • Shiro 系列教程

    Shiro 是一款安全框架,主要就是用来做验证和授权。 学习Shiro的痛苦 1.1 概念糊涂和混淆 Shiro ...

  • Apache Shiro

    Shiro安全框架简介 什么是Shiro? Apache的强大灵活的开源框架 认证、授权、企业会话管理、安全加密 ...

  • 一、Shiro简介

    目录:Shiro学习总结(目录贴) 1.1、Shiro是什么? Apache的强大并且灵活的开源安全框架。 简洁的...

  • Shiro系列笔记(1)

    shiro作为安全框架,提供了各种安全策略,此处记录身份认证Authentication的简单搭建步骤: (1)创...

  • 我的Shiro学习(一)

    前言 本文主要是记录自己学习Shiro框架的过程以及内容心得等,防止自己忘记。 什么是Shiro? Shiro是一...

  • 【Spring Boot】常见问题记录(持续更新..)

    问题1: Java 安全框架 shiro shiro是一个强大的Java安全框架,提供了认证、授权、加密、会话等功...

  • Spring Boot整合Shiro实现前后端分离

    一、Shiro简介   Apache Shiro是Java的一个安全框架。功能强大,使用简单的Java安全框架,它...

网友评论

      本文标题:Shiro安全框架学习记录

      本文链接:https://www.haomeiwen.com/subject/tjeiyctx.html