shiro权限控制框架的搭建

2.Shiro简介
2.1.是什么shiro?
Apache Shiro是一个强大且易用的Java安全框架,有身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
Spring security 重量级安全框架
Apache Shiro轻量级安全框架
2.2.shiro能干什么?
在这里插入图片描述
Shiro 开发团队称为“应用程序的四大基石” ——身份验证,授权,会话管理和加密作为其目标。
Authentication(身份认证):

有时也简称为“登录”,这是一个证明用户是他们所说的他们是谁的行为。
Authorization(授权):

访问控制的过程,也就是绝对“谁”去访问“什么”权限。
Session Management:管理用户特定的会话,即使在非 Web 或 EJB 应用程序。
Cryptography:通过使用加密算法保持数据安全同时易于使用。
也提供了额外的功能来支持和加强在不同环境下所关注的方面,尤其是以下这些:
Web Support: Shiro 的 web 支持的 API 能够轻松地帮助保护 Web 应用程序。
Caching:缓存是 Apache Shiro 中的第一层公民,来确保安全操作快速而又高效。
Concurrency: Apache Shiro 利用它的并发特性来支持多线程应用程序。
Testing:测试支持的存在来帮助你编写单元测试和集成测试,并确保你的能够如预期的一样安全。
“Run As”:一个允许用户假设为另一个用户身份(如果允许)的功能,有时候在管理脚本很有用。
“Remember Me”:在会话中记住用户的身份,所以他们只需要在强制时候登录。

2.3.架构
2.3.1.Shiro外部来看
从外部来看Shiro,即从应用程序角度来如何使用shiro来完成工作(认证、授权等)。
在这里插入图片描述
在这里插入图片描述
2.3.2.Shiro内部看
即shiro内部夹走
在这里插入图片描述
在这里插入图片描述
3.Shiro入门
前提:要一个Java Project
3.1.导入jar
在这里插入图片描述
3.2.拷贝资源
在这里插入图片描述
resources下面两个配置文件
log4j.properties
shiro.ini
java下面一个java文件
Quickstart.java
在这里插入图片描述
3.3.测试
Session数据
登录
授权


public class Quickstart {

    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);


    public static void main(String[] args) {

    	//通过一个配置了realms,users,roles,permissions的ini的配置文件快速创建一个SecurityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();

        //为了程序能偶正常运行,需要设置securityManager
        SecurityUtils.setSecurityManager(securityManager);

        //获取当前用户
        Subject currentUser = SecurityUtils.getSubject();

        //1 会话操作
        Session session = currentUser.getSession();//获取session
        session.setAttribute("someKey", "aValue");//在session中设置值
        String value = (String) session.getAttribute("someKey");//从session中获取值
        if (value.equals("aValue")) {
            log.info("Retrieved the correct value! [" + value + "]");
            //return;
        }

        //2 身份认证(登录)
        //如果没有登录
        if (!currentUser.isAuthenticated()) {
        	//把前台传入的用户名和密码创建一个UsernamePasswordToken
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);
            try {
            	//通过currentUser调用login传入UsernamePasswordToken执行登录操作,如果不正确就会抛出对应错误
                currentUser.login(token);
            } catch (UnknownAccountException uae) {
            	//用户不存在
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
            	//密码不正确
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
            	//账号被锁定
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            //其他异常-AuthenticationException是上面一样的父类
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

        //say who they are:
        //print their identifying principal (in this case, a username):
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        //3 权限
        //判断当前用户是否拥有该角色
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        //测试权限 lightsaber:*
        if (currentUser.isPermitted("lightsaber:weild")) {
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        //a (very powerful) Instance Level permission:
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

        //all done - log out!
        currentUser.logout();

        System.exit(0);
    }
}

3.4.总结
通过SecurityManger获取Suject
通过Subject来做事情:
获取Session-存值和获取值 Suject.getSession session.setAttribute session.getAttribute
认证(登录):
判断是否登录Suject.isAuthenticated
如果没有登录,通过用户名和密码创建UsernamePasswordToken
调用suject.login(UsernamePasswordToken)来进行登录判断
授权
判断是否具有某个角色subject .hasRole
判断是否有权限subject .isPrermited(resource:操作)

Log4j在项目中的使用

4.Shiro集成Spring
4.1.为什么要集成Spring
我们的项目基本都是通过Spring来管理bean的,如果要想使用Shiro,那就要把shiro集成到Spring。集成Spring的核心就是把框架的核心类(Subject,SecurityManager,Realm)交给Spring管理!
4.2.集成
4.2.1.准备Spring-web项目
拷贝ssm项目
4.2.2.集成

1)导入shiro-all-1.3.2.jar
参考官方demo做示例:
在这里插入图片描述
2)拷贝shiroFilter配置到web.xml
在这里插入图片描述
3)拷贝shiro Spring配置文件并集成到Spring
applicationContext.xml 改名为applicationContext-shiro.xml并在applicationContext.xml中导入
在这里插入图片描述
4)修改配置文件
在这里插入图片描述
在这里插入图片描述
5)测试
除了登录界面能够被正常访问,其他的都要跳转到登录界面!

4.3.小结
注意:需要一个Spring的环境,不能全部都在SpringMVC哪儿初始化
5.Authentication(身份认证)
5.1.引入
在集成Spring的例子中,只有登录页面是不需要登录可以直接访问。其他的页面需要认证(即登录)后才能访问,那怎么来实现登录认证,又叫做身份认证呢?

5.2.概念
在这里插入图片描述
做认证需要用户名和密码
认证流程:
在这里插入图片描述
5.3.详细步骤分析
要想实现登录,分前台和后台两部分:
前台:
实现一个login.jsp的页面,用来搜集登录信息(用户名和密码)!当点击登录时把登录信息提交到后台完成认证。
后台:
写一个Controller接收前台传入的登录信息,完成登录认证。
具体步骤如下:
1)创建LoginConroller,写一个方法接收前台登录请求并接受登录信息(用户名和密码)
2)获取当前的 Subject. 调用 SecurityUtils.getSubject();
3)测试当前的用户是否已经被认证. 即是否已经登录. 调用 Subject 的 isAuthenticated()
4)若没有被认证, 则把用户名和密码封装为 UsernamePasswordToken 对象
5)执行登录: 调用 Subject 的 login(AuthenticationToken) 方法.
6)自定义 Realm 的方法, 从数据库中获取对应的记录, 返回给 Shiro.
入门中使用的是Shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm。
实际上需要继承 org.apache.shiro.realm.AuthenticatingRealm 类
实现 doGetAuthenticationInfo(AuthenticationToken) 方法.
7)由 shiro 完成对密码的比对.
5.4.简单认证实现
在这里插入图片描述
在这里插入图片描述

5.5.简单实现总结
在这里插入图片描述
5.6.加密认证
分析:
1、密码不能明文保存到数据库 加密保存,比对也要加密比对,具体的比对CredentialsMatcher,默认使用就是SimpleCredentialsMatcher,不做加密的比对.要想做md5加密要使用HashedCredentialsMatcher,并且设置加密为md5
5.6.1.数据库加密保存

在这里插入图片描述
5.6.2.加密比对代码实现
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
5.7.盐值加密认证
为什么要使用盐值加密。盐值加密,更安全!
5.7.1.数据库要加密保存
在这里插入图片描述
5.7.2.认证时要支持盐值
在这里插入图片描述
5.8.盐值加密加次数认证
5.8.1.数据库要加密加盐加次数保存
在这里插入图片描述
5.8.2.认证时要支持次数
在这里插入图片描述
5.9.小结
普通认证
加密认证
加密加盐认证(采纳)

猜你喜欢

转载自blog.csdn.net/qq_41129811/article/details/84666557