SSM整合shiro 实现用户角色权限管理

ps:

一.环境:SpringMvc+spring+Mybatis,前后端分离,只支持单台项目(未实现单点登入);

二.需对shiro原理流程,有基础的理解,以及用户权限需求的应用场景明了,能更好项目整合;

三.shiro的基本构成:

    1.Subject (接口) : 主体(当前用户) 定义了认证授权的相关函数,通过SecurityManage 安全管理器进行授权按认证
    2.SecurityManage (接口)  : 框架核心核心 安全管理器,对subject进行认证,授权
        3.Authenticator : 认证器,对主体进行认证(登入)
        4.Authorizer : 授权器,通过认证后,在访问功能接口时,通过授权器判断用户是否有该功能的操作权限
        5.Realm : 读取用户权限数据, 进行安全认证需要通过realm,获取用户权限数据
    6.SessionManage : 会话管理器,自定义了一套,不依赖http的session
    7.SessionDAO : 操作会话信息,例如将会话信息存储到redis库
        8.CacheManage : 缓存管理器 ,将用户权限数据存储在缓存
    9.Cryptography : 加密

demo

1.maven依赖:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.4.1</version>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.8.0</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.1</version>
</dependency>

2.spring整合shiro配置:

1)spring.xml
<!--自定义的relam-->
<bean name="shiroRealm" class="hotkidclub.shiro.ShiroRealm"/>
<!--缓存管理器-->
<bean name="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"/>
<!--shiro安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="shiroRealm"/>
    <property name="cacheManager" ref="shiroCacheManager"/>
</bean>
<!-- 启动安全管理器: 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
    <property name="arguments" ref="securityManager"/>
</bean>
<!-- shiro 的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <!--如果没有认证将要跳转的登陆地址 -->
    <property name="loginUrl" value="/login"/>
    <!-- 配置安全规则:1). anon 可以被匿名访问
                  2). authc 必须认证(即登录)后才可能访问的页面 -->
    <property name="filterChainDefinitions">
        <value>
            <!-- 登录不拦截 -->
            / = anon
            /static/** = anon
            /login.ctrl = anon
            /** = authc
        </value>
    </property>
</bean>
<!-- AOP式方法级权限检查  -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
    <property name="proxyTargetClass" value="true"/>
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager"/>
</bean>
<!-- Shiro生命周期处理器-->
<bean name="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

2)web.xml

<!-- shiro过虑器 -->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>*.ctrl</url-pattern>
</filter-mapping>
<!-- 接收接口请求适配器 -->
<servlet>
    <servlet-name>backend_shiro_demo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value></param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>backend_shiro_demo</servlet-name>
    <url-pattern>*.ctrl</url-pattern>
</servlet-mapping>

3).自定义shiro的realm

package hotkidclub.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;

public class ShiroRealm extends AuthorizingRealm {

   /**
    * 认证器 :
    * <p>
    * 本平台用户登入接口调用-subject.login() : 回调该函数
    * </p>
    * 
    * @param authcToken 凭证信息:可存放用户账号密码
    * @return 认证信息:包含当前请求登入的用户信息
    * @throws AuthenticationException
    */
   @Override
   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
      System.out.println("认证开始");
      Subject subject = SecurityUtils.getSubject();
      // 1.获取认证的主体信息:账户密码...,TODO authcToken转换为本平台业务bean
      UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
      // 2.对比数据库存储的账号密码
      // 3.创建简单认证信息对象 : new SimpleAuthenticationInfo(object, object, 字符串);可传递自定义对象,字符内容;
      Session session = subject.getSession();
      session.setAttribute("user", token.getPrincipal());
      SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName());
      return info;
   }

   /**
    * 授权器 : 校验用户的角色和权限
    * <p>
    * 本平台接口配置角色/权限的授权注解时 : 回调该函数
    * </p>
    * 
    * @param principalCollection
    * @return
    */
   @Override
   protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
      // TODO 1.通过用户名去数据库查询该用户有哪些角色和权限
      // TODO 2.设置角色信息
      // TODO 3.设置权限信息
      // 创建简单授权信息对象
      SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
      info.addRole("admin");
      info.addStringPermission("add");
      System.out.println("鉴权完成");
      return info;
   }
}

3.测试

    //登入

    @ResponseBody
    @PostMapping(value = "/login.ctrl", produces = "application/json")
    public Map<String, Object> login(@RequestBody Map<String, Object> params, HttpSession httpSession) {
        Object object = null;
            // shiro login
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(账号,密码 );
            subject.login(token);
            object = result;
        
        return object;
    }
    
    
    /**
     * 测试:角色/权限的核查
     *
     * @param session
     * @return
     */
    @ResponseBody
    @RequiresRoles(value = "admin")//鉴查角色注解
    @RequiresPermissions(value = "add")//鉴权注解
    @GetMapping(value = "/check.ctrl", produces = "application/json") // @RequiresPermissions (value={"add", "update"}, logical= Logical.OR)
    public Map<String, Object> permission(HttpSession session) {
        String object = null;try {
            Subject subject = SecurityUtils.getSubject();
            object = "ok";
        }
        return object;
    }

发布了25 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_37794901/article/details/104059187