首页 > 其他分享 >Shiro

Shiro

时间:2022-12-25 00:22:05浏览次数:52  
标签:Shiro import apache org password shiro

1. 入门概述

1.1. 什么是Shiro?

Apache Shiro是一个功能强大且易于使用的Java安全(权限)框架。Shiro可以完成:认证、授权、加密、会话管理、与Web集成、换成等。借助Shiro可以快速轻松地保护任何应用程序————从最小的移动应用程序到最大的Web和企业应用程序。

Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.

Shiro官网:https://shiro.apache.org/

1.2. 基本功能

image
Shiro四大功能:认证登录,授权,会话管理和加密:

  • Authentication: Sometimes referred to as 'login', this is the act of proving a user is who they say they are.
  • Authorization: The process of access control, i.e. determining 'who' has access to 'what'.
  • Session Management: Managing user-specific sessions, even in non-web or EJB applications.
  • Cryptography: Keeping data secure using cryptographic algorithms while still being easy to use.

1.3. 架构

image

2. Shiro使用案例

2.1. 环境搭建

基于Maven项目搭建Shiro环境。

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.10.0</version>
</dependency>
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.1.1</version>
</dependency>

在resources文件夹中创建shiro.ini文件,用于提供入门案例的账户密码。

[users]
zhangsan=z3
lisi=l4

2.2. 登录认证

public class ShiroRun {
    public static void main(String[] args) {
        /*
         * 1. init SecurityManager
         * @Deprecated
         * Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
         * SecurityManager securityManager = factory.getInstance();
         * SecurityUtils.setSecurityManager(securityManager);
         */
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        IniRealm iniRealm = new IniRealm("classpath:shiro.ini");// shiro.ini在resources的根目录下
        securityManager.setRealm(iniRealm);
        SecurityUtils.setSecurityManager(securityManager);
        // 2. get object of class Subject
        Subject subject = SecurityUtils.getSubject();
        // 3. create object of class AuthenticationToken, get principle and credentials from data source(web page)
        AuthenticationToken token = new UsernamePasswordToken("zhangsan", "z3");
        // 4. login,throw exception if login fails
        try {
            subject.login(token);
            System.out.println("Login succeeded.");
        } catch (UnknownAccountException e) {
            System.out.println("User does not exist.");
        } catch (IncorrectCredentialsException e) {
            System.out.println("Password error.");
        } catch (AuthenticationException e) {
            // unexpected condition? error?
        }
    }
}

2.3. 角色授权

  • 编程式: 通过写if/else授权代码完成

if(subject.hasRole("admin")) {
      // have anthentication
} else {
      // no anthentication
}

  • 注解式: 通过在执行的Java方法上放置相应的注解完成,没有权限将抛异常

@RequiresRoles("admin")
public void hello() {
      // have anthentication
}

  • JSP标签: 在JSP页面通过相应的标签完成

<shiro:hasRole name="admin">
<!-- have anthentication -->
<shiro:hasRole>

修改shiro.ini,添加角色以及权限信息

[users]
zhangsan=z3, role1
lisi=l4, role2

[roles]
role1=user:insert, user:select
// 4. login,throw exception if login fails
try {
    subject.login(token);
    System.out.println("Login succeeded.");
    // 5. judge whether there is a role
    boolean hasRole = subject.hasRole("role1");
    System.out.println(hasRole);
    // 6. judge whether there is a permission
    boolean hasPermission = subject.isPermitted("user:insert");
    System.out.println(hasPermission);
} catch (AuthenticationException e) {
    // unexpected condition? error?
}

2.4. Md5加密

public class ShiroRun {
    public static void main(String[] args) {
        // clear-text passwords
        String password = "gty20021112";
        // md5 encryption
        Md5Hash md5Hash = new Md5Hash(password);
        System.out.println("md5 encryption: " + md5Hash);
        /*
         * encryption with salt, the salt means that
         * append a string to the end of original password then encrypting
         */
        Md5Hash md5HashWithSalt = new Md5Hash(password, "xuetian");
        System.out.println("md5 encryption with salt: " + md5HashWithSalt);
        // multiple encryption
        Md5Hash multiMd5HashWithSalt = new Md5Hash(password, "xuetian", 3);
        System.out.println("3 times md5 encryption with salt: " + multiMd5HashWithSalt);
    }
}

image

2.5. 自定义登录认证

Shiro默认的登录认证是不带加密的,如果想要实现加密认证需要自定义登录认证,自定义Realm。这里登录账号密码基于ini文件,需要再shiro.ini中添加配置信息。

[main]
md5CredentialsMatcher=org.apache.shiro.authc.credential.Md5CredentialsMatcher
Md5CredentialsMatcher.hashIterations=3

customRealm=com.example.CustomRealm
customRealm.credentialsMatcher=$md5CredentialsMatcher
securityManager.realm=$customRealm

[users]
zhangsan=d954b66f8e663abea8317592a1d4d6aa, role1
lisi=l4, role2

[roles]
role1=user:insert, user:select

重写doGetAuthenticationInfo方法

/**
 * 自定义登录认证方法,shiro的login方法底层会调用该类的认证方法进行认证
 * 需要配置自定义的realm生效,再ini文件中配置或与Spring整合后进行配置
 */
public class CustomRealm extends AuthenticatingRealm {

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 1. get principle
        String principal = (String) token.getPrincipal();
        // 2. get credentials
        String credentials = (String) token.getCredentials();
        // 3. get user information from database
        if ("zhangsan".equals(principal)) {
            // the password get from database
            String password = "d954b66f8e663abea8317592a1d4d6aa";
            // 封装校验逻辑对象并返回
            return new SimpleAuthenticationInfo(
                    token.getPrincipal(),// 登录输入的密码(未加密)
                    password,// 数据库中查询的密码(加密)
                    ByteSource.Util.bytes("xuetian"),// 盐的名称
                    token.getPrincipal().toString()// realm的名称(一般用登录用户名)
            );
        }
        return null;
    }
}

3. Spring整合Shiro框架

在pom.xml中导入以下依赖。

<!--shiro-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.10.0</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-web</artifactId>
    <version>1.10.0</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.10.0</version>
</dependency>

CustomRealm.java

import com.gty.entity.Member;
import com.gty.service.MemberService;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    private MemberService memberService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //TODO
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 1. get principle
        String principal = (String) token.getPrincipal();
        // 2. get user information from database
        Member member = memberService.loadMemberByUsername(principal);
        if (member != null) {
            // 3. the password get from database
            String password = member.getPassword();
            return new SimpleAuthenticationInfo(
                    token.getPrincipal(),
                    password,
                    ByteSource.Util.bytes("xuetian"),// the salt's name
                    "realmName"// the name of realm
            );
        }
        return null;
    }
}

spring_shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--扫描组件(CustomRealm)-->
    <context:component-scan base-package="com.gty.security"/>

    <!-- 配置自定义realm -->
    <bean id="customRealm" class="com.gty.security.CustomRealm">
        <property name="credentialsMatcher">
            <!-- 配置加密器 -->
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <property name="hashAlgorithmName" value="MD5"/>
                <property name="hashIterations" value="1024"/>
            </bean>
        </property>
    </bean>

    <!-- 配置SecurityManager安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="customRealm" />
    </bean>

    <!-- 配置Shiro的Web过滤器, bean id必须与web.xml中配置的名称相同 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 配置SecurityManager安全管理器 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 如果没有认证,则跳转到登录页面 -->
        <property name="loginUrl" value="/login"/>
        <!-- 如果没有权限,则跳转到指定页面 -->
        <property name="unauthorizedUrl" value="/unauthorized"/>
        <!--登陆成功-->
        <property name="successUrl" value="/index"/>
        <!-- Shiro过滤器链 -->
        <property name="filterChainDefinitions">
            <value>
                /member/login = anon
                /member/logout = logout
                /** = authc
                /js/** anon
                /images/** anon
                /styles/** anon
            </value>
        </property>
    </bean>
</beans>

在web.xml中添加

<!-- shiro过滤器,DelegatingFilterProxy作用是自动到spring容器查找名字为shiroFilter(filter-name)的bean并把所有Filter的操作委托给它,ShiroFilter需要配置到spring容器 -->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <!-- 设置true由servlet容器控制filter的生命周期 -->
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
    <!-- 设置spring容器filter的bean id,如果不设置则找与filter-name一致的bean-->
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>shiroFilter</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

login.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <h1>Shiro登录认证</h1>
  <form th:action="@{/member/login}" method="get">
      <div><input type="text" name="username" value=""/></div>
      <div><input type="password" name="password" value=""/></div>
      <div><button type="submit">登录</button></div>
  </form>
</body>
</html>

标签:Shiro,import,apache,org,password,shiro
From: https://www.cnblogs.com/hualuosakura/p/16997529.html

相关文章

  • shiro集成CAS遇到的问题
    O在继承单点登陆的时候shiro和cas服务器中的session的有效时间不一致,这个时候就导致了当shiro的session失效的时候调用到cas服务器的登陆这个时候就会跳转不过去,从而导致了......
  • shiro整合thymeleaf
    1、依赖<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.10.0</ver......
  • shiro使用
    1、依赖<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.10.0</ver......
  • springboot整合shiro的问题
      妈妈的 真的复制快捷一时爽  就是这个默认的连接池的类型是错误的  写错了  所以才一直注册不了bean  妈妈呀  我干  浪费我3个多小时 心态......
  • Session和Shiro的Session区别
    tomcat中的session常出现为jsessionId,而shiro的session不相同,两者的id不同。在controller中,通过request.getSession(_)获取会话session,该session到底来源servletReque......
  • heapdump泄露Shiro key从而RCE
    1.简介我搭建了一个Springheapdump泄露shirokey从而RCE的漏洞环境,Github地址:https://github.com/P4r4d1se/heapdump_shiro_vuln漏洞利用条件:SpringShiro环境存在heapdu......
  • shiro源码第一天:登陆验证部分
    登陆验证部分:​​1.单点登陆系统中不同系统密码验证方式不一样​​1.单点登陆系统中不同系统密码验证方式不一样问题:当使用shiro作为鉴权框架时,首先用到的应该就是登陆认证......
  • Shiro权限 表设计
    表设计权限管理需要的基本表有5个如下:sys_users用户表sys_roles角色表sys_permissions权限表(或资源表)sys_users_roles用户-角色关联表sys_roles_permissions角色-......
  • shiro低版本更新到高版本(>1.10.0)出现报错问题解决
    近期漏洞爆出(ApacheShiro<1.10.0身份认证绕过漏洞),开始升级新版的jar包。升级过程1.修改pom文件shiro版本<!--shiro--><dependency><groupId>org.apache.......
  • shiro550
    0x00前言结束了cc链的学习,准备学习一手shiro反序列化漏洞嘛,这个漏洞其实出现了蛮久了是这两年攻防才把它逐渐的提上来,也大概知道这个漏洞的原理就是加迷是用的aes而且密钥......