shiro的认证流程

Application Code:应用程序代码,由开发人员负责开发的

Subject:框架提供的接口,代表当前用户对象

SecurityManager:框架提供的接口,代表安全管理器对象

Realm:可以开发人员编写,框架也提供一些,类似于DAO层,用于访问权限数据

引入maven依赖


<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-all -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>

配置web.xml


<!-- 配置Spring框架提供的用于整合Shiro框架的过滤器 shiro 过滤器一定要保证 要先进入!!
这个过滤器的名字必须与Spring配置文件中的ben配置id相同
--> <filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

在Spring配置文件中配置shiro



    <!--shiro 配置方式-->

    <!--注册realm-->
<bean id="myRealm" class="top.wintp.crud.service.MyRealm"/> <!--配置安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean> <!--配置shiro过滤器工厂对象-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!--securityManager 注入安全管理器-->
<property name="securityManager" ref="securityManager"/> <!--注入相关页面的访问URL--> <property name="loginUrl" value="/user/login.do"/>
<!--<property name="successUrl"/>-->
<property name="unauthorizedUrl" value="/user/unAuth.do"/> <!--
注入URL拦截规则
-->
<property name="filterChainDefinitions">
<value>
/static/** = anon
/user/login.do=anon
/user/loginUser.do=anon
/emp/findAll.do=perms["admin"]
/** = authc
</value>
</property> </bean>

MyRealm

package top.wintp.crud.service;

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.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import top.wintp.crud.dao.TUserMapper;
import top.wintp.crud.entity.TUser;
import top.wintp.crud.entity.TUserExample; /**
* 类描述:
* <p>
* 作者: pyfysf
* <p>
* qq: 337081267
* <p>
* CSDN: http://blog.csdn.net/pyfysf
* <p>
* 个人博客: http://wintp.top
* <p>
* 邮箱: pyfysf@163.com
* <p>
* 时间:2018/8/22
*/
public class MyRealm extends AuthorizingRealm { @Autowired
private TUserMapper mTUserMapper; @Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("自定义realm授权方法"); @Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("自定义realm授权方法");
TUser user = (TUser) principalCollection.getPrimaryPrincipal(); System.out.println(user.getUsername());
System.out.println(user.getPassword()); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addStringPermission("admin"); //授权
return authorizationInfo;
} @Override
protected AuthenticationInfo
doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("自定义realm认证方法"); UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; TUserExample tUserExample = new TUserExample();
tUserExample.createCriteria().andUsernameEqualTo(token.getUsername());
List<TUser> tUsers = mTUserMapper.selectByExample(tUserExample); if (tUsers != null && tUsers.size() > 0) { TUser tUser = tUsers.get(0); //简单认证信息对象
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(tUser, tUser.getPassword(), this.getName()); //认证
return authenticationInfo;
} else {
return null;
} }
}

修改用户登录的方法

@Service
public class UserService { public boolean loginUser(TUser user) { String username = user.getUsername(); //shiro执行过程 获取当前用户--subject -->然后获取securityManager(安全管理器)(login 登录)
// 然后调用realm //获取当前用户对象 -- 未认证
Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token
= new UsernamePasswordToken(user.getUsername(), user.getPassword()); try {
subject.login(token); TUser resultUer = (TUser) subject.getPrincipal(); System.out.println("登录成功"); return true; } catch (Exception e) {
//代表认证失败
e.printStackTrace(); return false;
}
}
}

常用过滤器配置简称

注解式编程

首先需要在Spring的配置文件中开启Shiro的注解支持:在applicationContext.xml中加入下面代码:


<!--开启shiro 框架的注解支持-->
<bean id="advisorAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<!--默认开启CGLIB代理-->
<property name="proxyTargetClass" value="true"/>
</bean> <!--配置切面 用于创建代理对象-->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/>

有了上面的配置,我们就可以在我们的代码中使用Shiro的注解进行权限控制了:


@RequestMapping("/findAll")
@RequiresPermissions("emp-check")
public String findAll(Model model, @RequestParam(value = "pageNum", defaultValue = "1")
Integer pageNum) { logger.info("请求开始>>>>>"); //书写分页逻辑--在这里进行分页声明之后,后面紧跟的查询就是一个分页目标
//第二个参数是指定每次查询几条数据
PageHelper.startPage(pageNum, 5); //调用Service里面的方法进行使用
List<Employee> allEmployees = mEmployeeService.findAll();
//使用PageInfo来包装返回的数据--可以更好的管理分页逻辑 //第二个参数是页面上最多显示几个页数,比如限制只显示5个那么就为1,2,3,4,5
//2,3,4,5,6||||3,4,5,6,7
PageInfo<Employee> employeePageInfo = new PageInfo<Employee>(allEmployees, 5); logger.info("数据为:" + employeePageInfo); logger.info("请求结束>>>>>"); //存储数据,跳转界面
model.addAttribute("employeePageInfo", employeePageInfo);
return "list";
}

中途遇到的问题

配置注解之后,没有起到任何作用。

可能一:在你的spring的配置文件中忽略扫描Controller注解,然而你在Controller中使用了@RequiresPermissions,那么我们需要把上面注解支持的代码配置到Spring-mvc.xml文件中。


<!--扫描所有包-->
<context:component-scan base-package="top.wintp.crud">
<!--除了控制器 都进行注解扫描-->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/> </context:component-scan>

如果有上面的配置,那么spring将不会扫描到Controller注解

可能二:在你的spring-mvc中仅仅只是扫描到了Controller注解,然而你在service层或者dao层用到了@RequiresPermissions,那么我们需要把上面注解支持的代码配置到applicationContext.xml文件中。

  <context:component-scan base-package="top.wintp.crud" use-default-filters="false">
<!--只扫描控制器即可-->
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/> </context:component-scan>

建议:在Spring的主配置文件中和Springmvc的配置文件中都加入对shiro注解的支持。特别注意:如果两个配置文件中都配置了,注意其id不能相同

在jsp中使用shiro提供的标签库

一、引入标签库
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
二、使用合适的标签在合适的位置进行使用

例如:

<shiro:hasPermission name="admin">

    <button class="btn btn-primary" id="btn_add_emp">新增</button>
<button class="btn btn-danger btn_all_del">删除</button>
</shiro:hasPermission>

上述代码为,当当前用户具有admin的权限时,新增和删除按钮才会显示

最新文章

  1. 关键帧动画:@keyframes
  2. Issue 0:发刊词
  3. java集合-集合大家族
  4. struts1
  5. java 21 - 10 文本文件和集合之间互相存储数据
  6. medoo数据库插入的问题
  7. PHP下利用PHPMailer配合QQ邮箱下的域名邮箱发送邮件
  8. 一起来Fit TDMA over WiFi(1)
  9. linux进程的介绍和管理
  10. 解决 “MoveFile”: 类型库“XXX.dll”中的标识符已经是宏;使用“rename”限定符 类型库符号与系统符号冲突问题
  11. Niagara 泵阀
  12. Mysql相关问题集锦
  13. PAT 1056 组合数的和
  14. yum 快速安装centos7 mysql5.7
  15. 1、 LwIP协议栈规范翻译——简介
  16. Vim正则表达式匹配替换字符串
  17. 转:ffmpeg time_base详解
  18. HTML CSS 表格换行禁止 超出指定长度自动截断
  19. DQL-条件查询
  20. RabbitMQ之Consumer消费模式(Push &amp; Pull)

热门文章

  1. Cookieless.js —— 无需 Cookie 实现访客跟踪
  2. Java基础(五) final关键字浅析
  3. SpringBoot2.1.6 整合CXF 实现Webservice
  4. 05 div的嵌套
  5. MySQL8.0 DDL原子性特性
  6. vuex分模块2
  7. easyui combobox name选择器
  8. Don’t Repeat Yourself
  9. 最近学习了HBase
  10. .NET Core 3.0之深入源码理解Kestrel的集成与应用(二)