博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Shiro基础:简单用户认证+权限测试+自定义安全策略+MD5加密
阅读量:3961 次
发布时间:2019-05-24

本文共 11423 字,大约阅读时间需要 38 分钟。

目录

1.简介

1.1什么是Shiro

Apache Shiro(日语“堡垒(Castle)”的意思)是一个强大易用的Java安全框架,

提供了认证、授权、加密和会话管理功能,可为任何应用提供安全保障 - 从命令行应用、移动应用到大型网络及企业应用。
Apache Shiro 是一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密。
Apache Shiro 的首要目标是易于使用和理解。安全有时候是很复杂的,甚至是痛苦的,但它没有必要这样。框架应该尽可能掩盖复杂的地方,露出一个干净而直观的 API,来简化开发人员在使他们的应用程序安全上的努力。以下是你可以用 Apache Shiro 所做的事情:
 验证用户来核实他们的身份
 对用户执行访问控制,如:
 判断用户是否被分配了一个确定的安全角色
 判断用户是否被允许做某事
 在任何环境下使用 Session API,即使没有 Web 或 EJB 容器。
 在身份验证,访问控制期间或在会话的生命周期,对事件作出反应。
 聚集一个或多个用户安全数据的数据源,并作为一个单一的复合用户“视图”。
 启用单点登录(SSO)功能。
 为没有关联到登录的用户启用"Remember Me"服务
以及更多——全部集成到紧密结合的易于使用的 API 中。
Shiro 视图在所有应用程序环境下实现这些目标——从最简单的命令行应用程序到最大的企业应用,不强制依赖其他第三方框架,容器,或应用服务器。当然,该项目的目标是尽可能地融入到这些环境,但它能够在任何环境下立即可用。

1.2Shiro整体架构图

在这里插入图片描述

  1. Subject:主体,可以看到主体可以是任何与应用交互的“用户”。
    2. SecurityManager:相当于 SpringMVC 中的 DispatcherServlet 或者 Struts2 中的FilterDispatcher。它是 Shiro 的核心,所有具体的交互都通过 SecurityManager 进行控制。它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理。
    3. Authenticator:认证器,负责主体认证的,这是一个扩展点,如果用户觉得 Shiro 默认的不好,我们可以自定义实现。其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了。
    4. Authrizer:授权器,或者访问控制器。它用来决定主体是否有权限进行相应的操作,即控制着用户能访问应用中的哪些功能。
    5. Realm:可以有1个或多个 Realm,可以认为是安全实体数据源,即用于获取安全实体的。它可以是 JDBC 实现,也可以是 LDAP 实现,或者内存实现等。
    6. SessionManager:如果写过 Servlet 就应该知道 Session 的概念,Session 需要有人去管理它的生命周期,这个组件就是 SessionManager。而 Shiro 并不仅仅可以用在 Web 环境,也可以用在如普通的 JavaSE 环境。
    7. SessionDAO:DAO 大家都用过,数据访问对象,用于会话的 CRUD。我们可以自定义 SessionDAO 的实现,控制 session 存储的位置。如通过 JDBC 写到数据库或通过 jedis 写入 redis 中。另外 SessionDAO 中可以使用 Cache 进行缓存,以提高性能。
    8. CacheManager:缓存管理器。它来管理如用户、角色、权限等的缓存的。因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能。
    9. Cryptography:密码模块,Shiro 提高了一些常见的加密组件用于如密码加密/解密的

2.测试代码

2.1.目录结构

在这里插入图片描述

2.2pom.xml

4.0.0
org.springframework.boot
spring-boot-starter-parent
2.0.3.RELEASE
com.wo
shiro_test
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
true
mysql
mysql-connector-java
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.1.1
org.apache.shiro
shiro-spring
1.4.0

2.3application.yml

spring:  datasource:    driver-class-name: com.mysql.jdbc.Driver    username: root    password: 123456    url: jdbc:mysql://localhost:3306/test4?useUnicode=true&characterEncoding=utf8&useSSL=falsemybatis:  mapper-locations: classpath:mapper/*Mapper.xml

3.简单的用户认证

3.1 shiro_first.ini

[users]zhangsan=123lisi=123

3.2TestShiro

@RunWith(SpringRunner.class)@SpringBootTestpublic class TestShiro {
@Test public void testFirstShiro(){
//使用IniSecurityManagerFactory加载shiro_first.ini文件 IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro_first.ini"); //使用工厂类创建securityManager SecurityManager securityManager = iniSecurityManagerFactory.createInstance(); //使用shiro提供的工具类来创建manager的运行环境 SecurityUtils.setSecurityManager(securityManager); //使用工具类获取我们的主体部分 Subject subject = SecurityUtils.getSubject(); //设置用户名及密码部分 //前端用户传输的用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken("lisi", "123"); //从主题中开始登录 try {
subject.login(token); System.out.println("用户登录成功!!!!!!!!"); }catch (IncorrectCredentialsException inc){
System.out.println("用户登录失败!!!!!!!!!失败原因 密码错误!!!"); }catch (UnknownAccountException uae){
System.out.println("用户登录失败!!!!!!!!失败原因,没有该用户名"); } if(subject.isAuthenticated()){
System.out.println("验证通过"); }else{
System.out.println("验证失败"); } }}

4.拥有权限的简单测试

4.1shiro_permission.ini

[users]normal=123,role1admin=admin,role2root=root,role3[roles]role1=user:selectrole2=user:select,user:updaterole3=user:creat,user:delete,user:select,user:update

4.2TestShiroPermissions

@RunWith(SpringRunner.class)@SpringBootTestpublic class TestShiroPermissions {
@Test public void testUserPermissions(){
//使用IniSecurityManagerFactory加载shiro_first.ini文件 IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro_permission.ini"); //使用工厂类创建securityManager SecurityManager securityManager = iniSecurityManagerFactory.createInstance(); //使用shiro提供的工具类来创建manager的运行环境 SecurityUtils.setSecurityManager(securityManager); //使用工具类获取我们的主体部分 Subject subject = SecurityUtils.getSubject(); //设置用户名及密码部分 //前端用户传输的用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken("root", "root"); //从主题中开始登录 try {
subject.login(token); System.out.println("用户登录成功!!!!!!!!"); }catch (IncorrectCredentialsException inc){
System.out.println("用户登录失败!!!!!!!!!失败原因 密码错误!!!"); }catch (UnknownAccountException uae){
System.out.println("用户登录失败!!!!!!!!失败原因,没有该用户名"); } //判断用户的角色 String rol="role2"; boolean hasRole = subject.hasRole(rol); if(hasRole){
System.out.println("用户拥有"+rol+"角色"); }else {
System.out.println("用户没有"+rol+"角色"); } //判断用户权限 String per="user:delete"; boolean b = subject.isPermitted(per); if (b){
System.out.println("用户拥有"+per+"权限"); }else {
System.out.println("用户没有"+per+"权限"); } //批量验证该用户的角色 boolean[] hasRoles = subject.hasRoles(Arrays.asList("role1", "role2", "role3")); System.out.println(Arrays.toString(hasRoles)); //批量验证该用户的权限 boolean[] permitted = subject.isPermitted("user:creat", "user:delete"); System.out.println(Arrays.toString(permitted)); //验证用户是否拥有输入的全部权限 boolean permittedAll = subject.isPermittedAll("user:creat", "user:delete"); System.out.println(permittedAll); }}

5.自定义安全策略的shiro应用案例:

5.1shiro_myrealm.ini

[main]#自定义realmmyrealm=com.wo.shiro.MyRealm#在shiro核心中,设置自定义myrealmsecurityManager.realms=$myrealm

5.2MyRealm

public class MyRealm extends AuthorizingRealm {
//授权的方法 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//获取到前端传输的用户名 String username = (String) principals.getPrimaryPrincipal(); //使用前端传输用户名5表联查,获取到用户的所拥有的权限信息 HashSet
objects=new HashSet<>(); objects.add("user:create"); objects.add("user:update"); //声明simpleAuthorizationInfo 对象 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //将权限放置到声明simpleAuthorizationInfo 对象中 simpleAuthorizationInfo.setStringPermissions(objects); //放置角色 simpleAuthorizationInfo.addRole("role1"); return simpleAuthorizationInfo; } //认证的方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取到前端传输的用户名 String username = (String) token.getPrincipal(); //使用前端用户名去数据库查询正确的密码 String password="123"; //将前端传输过来的用户名,以及使用该用户名 查询到的正确密码放置到查询出的正确密码放置到simpleAuthticationinfo中进行返回 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, getName()); return simpleAuthenticationInfo; }}

5.3 TestShiroMyRealm

@RunWith(SpringRunner.class)@SpringBootTestpublic class TestShiroMyRealm {
@Test public void testMyRealm(){
//使用IniSecurityManagerFactory加载shiro_first.ini文件 IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro_myrealm.ini"); //使用工厂类创建securityManager SecurityManager securityManager = iniSecurityManagerFactory.createInstance(); //使用shiro提供的工具类来创建manager的运行环境 SecurityUtils.setSecurityManager(securityManager); //使用工具类获取我们的主体部分 Subject subject = SecurityUtils.getSubject(); //设置用户名及密码部分 //前端用户传输的用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken("root", "123"); //从主题中开始登录 try {
subject.login(token); System.out.println("用户登录成功"); }catch (IncorrectCredentialsException ex){
System.out.println("用户登录失败,失败原因:密码错误"); } boolean b = subject.hasRole("role2"); if (b){
System.out.println("用户拥有该角色"); }else {
System.out.println("用户没有该角色"); } boolean permitted = subject.isPermitted("user:create"); if (permitted){
System.out.println("用户拥有该权限"); }else {
System.out.println("用户没有该权限"); } }}

6.自定义安全策略并凭证MD5加密的shiro应用案例

6.1shiro_myrealmMd5.ini

[main]#定义凭证匹配器credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher#设置散列算法credentialsMatcher.hashAlgorithmName=md5#设置散列次数credentialsMatcher.hashIterations=1#将凭证匹配器设置到realmmyRealm=com.wo.shiro.MyRealmMD5myRealm.credentialsMatcher=$credentialsMatchersecurityManager.realms=$myRealm

6.2MyRealmMD5

public class MyRealmMD5 extends AuthorizingRealm{
//权限 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal(); //用username 去数据库获取加密后的密码 202cb962ac59075b964b07152d234b70 String password="202cb962ac59075b964b07152d234b70"; SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, getName()); return simpleAuthenticationInfo; }}

6.3TestShiroMd5MyRealm

@RunWith(SpringRunner.class)@SpringBootTestpublic class TestShiroMd5MyRealm {
@Test public void testMd5(){
//使用IniSecurityManagerFactory加载shiro_first.ini文件 IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro_myrealmMd5.ini"); //使用工厂类创建securityManager SecurityManager securityManager = iniSecurityManagerFactory.createInstance(); //使用shiro提供的工具类来创建manager的运行环境 SecurityUtils.setSecurityManager(securityManager); //使用工具类获取我们的主体部分 Subject subject = SecurityUtils.getSubject(); String username = "zhangsan"; String password = "123"; UsernamePasswordToken token = new UsernamePasswordToken(username, password); try {
subject.login(token); System.out.println("用户登录成功"); }catch (IncorrectCredentialsException inc){
System.out.println("用户登录失败"); } }}

转载地址:http://icezi.baihongyu.com/

你可能感兴趣的文章
Source Insight 经典教程
查看>>
快速打开菜单附件中的工具
查看>>
Windows系统进程间通信
查看>>
linux exec的用法
查看>>
C语言中如何使用宏
查看>>
Http与RPC通信协议的比较
查看>>
Source Insight的对齐问题
查看>>
ubuntu设置开机默认进入字符界面方法
查看>>
chrome 快捷键
查看>>
Linux下buffer和cache的区别
查看>>
程序员不应该再犯的五大编程错误
查看>>
[转载][转帖]Hibernate与Sleep的区别
查看>>
Linux系统的默认编码设置
查看>>
Linux系统调用
查看>>
Linux 信号signal处理机制
查看>>
Linux 信号signal处理函数
查看>>
perror简介
查看>>
linux的system () 函数详解
查看>>
在shell脚本的第一行中,必须写#!/bin/bash
查看>>
一句话##错误 'ASP 0116' 丢失脚本关闭分隔符
查看>>