spring+shiro授权简单实现

本是古典 何须时尚 2022-06-02 00:14 341阅读 0赞

写代码之前,我们需要了解什么是授权,有什么用?
授权,也成访问资源控制,主要是管理使用者看到或操作的内容,(如访问页面/编辑数据/页面操作等)。

  • 权限
    通过权限我们可以知道用户能做哪些事,如访问某个页面,以及对某个模块的数据的添加,修改,删除,查看的权利;
    可以看出,权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允许,不反映谁去执行这个操作。所以后续还需要把权限赋予给用户,即定义哪个用户允许在某个资源上做什么操作(权限),Shiro不会去做这件事情,而是由实现人员提供。
  • 角色
    可以把角色认做事权限的集合,通过分配给用户角色来实现赋予权限时比较方便。典型的如:项目经理、技术总监、CTO、开发工程师等都是角色,不同的角色拥有一组不同的权限。
    o o 隐式角色:即直接通过角色来验证用户有没有操作权限,如在应用中CTO、技术总监、开发工程师可以使用打印机,假设某天不允许开发工程师使用打印机,此时需要从应用中删除相应代码;再如在应用中CTO、技术总监可以查看用户、查看权限;突然有一天不允许技术总监查看用户、查看权限了,需要在相关代码中把技术总监角色从判断逻辑中删除掉;即粒度是以角色为单位进行访问控制的,粒度较粗;如果进行修改可能造成多处代码修改。
    o o 显示角色:在程序中通过权限控制谁能访问某个资源,角色聚合一组权限集合;这样假设哪个角色不能访问某个资源,只需要从角色代表的权限集合中移除即可;无须修改多处代码;即粒度是以资源/实例为单位的;粒度较细。
  • 主体
    即访问应用的用户,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;即一个抽象概念;所有Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者;但是为了方便理解,可以理解成用户,
  • 资源
    在应用中用户可以访问的任何东西,比如访问JSP页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问。

代码配置

我dao层使用的是jpa(hibernate),

  1. <?xml version="1.0" encoding="UTF-8"?><!-- @version $Id: applicationContext.xml 561608 2007-08-01 00:33:12Z vgritsenko $ -->
  2. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
  3. <!--跟shiro整合-->
  4. <!--使用注解进行权限控制-->
  5. <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
  6. <property name="proxyTargetClass" value="true"/> <!--强制代理生成方式使用cglib-->
  7. </bean>
  8. <!--配置切面类-->
  9. <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/>
  10. <!--设置成cglib代理-->
  11. <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
  12. <!--配置过滤器-->
  13. <bean id="shiro" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  14. <property name="loginUrl" value="/login.html"></property>
  15. <property name="successUrl" value="/index.html"></property>
  16. <property name="securityManager" ref="securityManager"></property>
  17. <property name="unauthorizedUrl" value="/unauthorized.html"></property>
  18. <!--设置规则-->
  19. <property name="filterChainDefinitions">
  20. <value>
  21. /css/** = anon
  22. /images/** = anon
  23. /js/** = anon
  24. /validatecode.jsp* = anon
  25. /userAction_login.* = anon
  26. /**=authc
  27. </value>
  28. </property>
  29. </bean>
  30. <!--配置管理者,核心类-->
  31. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  32. <property name="realm" ref="realm"></property>
  33. </bean>
  34. <!--配置realm-->
  35. <bean id="realm" class="cn.itcast.bos.web.realm.LoginRealm"></bean>
  36. <!--开启注解扫描-->
  37. <context:component-scan base-package="cn.itcast.demo"/>
  38. <!-- 整合 spring data jpa -->
  39. <jpa:repositories base-package="cn.itcast.dao" />
  40. <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  41. <property name="entityManagerFactory" ref="entityManagerFactory"/>
  42. </bean>
  43. <!--连接池-->
  44. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  45. <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
  46. <property name="jdbcUrl" value="jdbc:oracle:thin:@192.168.129.100:1521:orcl"/>
  47. <property name="user" value="xiaoyang"/>
  48. <property name="password" value="xy123"/>
  49. </bean>
  50. <!--spring 跟 jpa整合-->
  51. <!--配置factory-->
  52. <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  53. <property name="dataSource" ref="dataSource"/>
  54. <!--包扫描-->
  55. <property name="packagesToScan" value="cn.itcast.domain"/>
  56. <!--持久层使用hibernate框架-->
  57. <property name="persistenceProvider" >
  58. <bean class="org.hibernate.ejb.HibernatePersistence"/>
  59. </property>
  60. <property name="jpaVendorAdapter">
  61. <!-- 自动建表 -->
  62. <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
  63. <property name="showSql" value="true"/>
  64. <property name="generateDdl" value="true"/>
  65. <property name="database" value="ORACLE"/>
  66. <!--其实就是数据库方言-->
  67. <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect"/>
  68. </bean>
  69. </property>
  70. <property name="jpaDialect">
  71. <!--hql hqpl-->
  72. <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
  73. </property>
  74. </bean>
  75. </beans>

注解式授权

  1. @Transactional
  2. @Service
  3. public class CourierServiceImpl implements ICourierService {
  4. @Resource
  5. IDemoDao idao;
  6. @RequiresPermissions("aa") // 需要aa权限才能执行该方法
  7. // @RequiresRoles("pipixia") 需要pipixia的角色才能调用
  8. public void save(Courier courier) {
  9. icd.save(courier);
  10. }
  11. }

我们不授权,运行来看效果.
这里写图片描述

来看看报错信息
这里写图片描述

信息说没有aa的权限,

我们加一个权限试试,登陆的realm中,

  1. package cn.itcast.bos.web.realm;
  2. import cn.itcast.bos.dao.system.IUserDao;
  3. import cn.itcast.domain.system.User;
  4. import org.apache.shiro.authc.*;
  5. import org.apache.shiro.authz.AuthorizationInfo;
  6. import org.apache.shiro.authz.SimpleAuthorizationInfo;
  7. import org.apache.shiro.realm.AuthenticatingRealm;
  8. import org.apache.shiro.realm.AuthorizingRealm;
  9. import org.apache.shiro.realm.Realm;
  10. import org.apache.shiro.subject.PrincipalCollection;
  11. import javax.annotation.Resource;
  12. public class LoginRealm extends AuthorizingRealm {
  13. @Resource
  14. private IDemoDao idao;
  15. @Override //认证的方法
  16. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
  17. //下塑转型
  18. UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
  19. String username = token.getUsername();
  20. User user = idao.findByUsername(username);
  21. if (user == null){
  22. return null;
  23. }
  24. return new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
  25. }
  26. @Override //授权的方法
  27. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
  28. SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
  29. info.addStringPermission("aa"); //给登陆用户一个aa权限,
  30. return info;
  31. }
  32. }

然后我们再来运行一遍,看运行结果,
这里写图片描述

运行成功,证明了授权逻辑是没有问题的,

编程式授权

还是save方法,继续测试

  1. // @RequiresPermissions("aa") // 需要aa权限
  2. // @RequiresRoles("pipixia") 需要pipixia的角色才能调用
  3. public void save(Courier courier) {
  4. // SecurityUtils.getSubject()
  5. Subject subject = SecurityUtils.getSubject();
  6. subject.checkRole("pipixia"); //如果没有pipixia的角色,那么调用会被拒绝
  7. icd.save(courier);
  8. }

然后走测试方法

这里写图片描述

说我们没有皮皮虾的角色权限,

我们来添加一个角色权限

  1. public class LoginRealm extends AuthorizingRealm {
  2. @Resource
  3. private IUserDao idao;
  4. @Override //认证的方法
  5. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
  6. //下塑转型
  7. UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
  8. String username = token.getUsername();
  9. User user = idao.findByUsername(username);
  10. if (user == null){
  11. return null;
  12. }
  13. return new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
  14. }
  15. @Override //授权的方法
  16. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
  17. SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
  18. //给用户增加一个pipixia权限
  19. info.addRole("pipixia");
  20. return info;
  21. }
  22. }

添加完权限后,我们再来测试

这里写图片描述

授权的简单实现就讲到这里,下一次我们结合表来做 认证+授权

发表评论

表情:
评论列表 (有 0 条评论,341人围观)

还没有评论,来说两句吧...

相关阅读

    相关 shiro实现授权

    1,授权概述 授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作 等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Reso