本站网址
www.kjyfx.com

『Java』Shiro权限认证框架的整合及相关配置

一、Shrio主要核心功能

三个核心组件:Subject, SecurityManager 和 Realms

Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,必须至少指定一个Realm(如需认证,则需要继承AuthenticatingRealm,并重写doGetAuthenticationInfo认证方法进行认证;如需授权,则需继承AuthorizingRealm,并重写doGetAuthenticationInfo认证方法与doGetAuthorizationInfo授权方法),用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。

二、Spring Boot整合Shiro(根据需要参考)

所需依赖

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

 

1、创建Shiro配置类

 

package com.kjyfx.common.config;

import java.util.LinkedHashMap;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;


@Configuration
public class SpringShiroConfig {

    /**shiro的核心管理器对象(负责提供认证和授权操作)*/
    @Bean 
    public SecurityManager securityManager(
        Realm realm,CacheManager cacheManager) {
        DefaultWebSecurityManager sm = new DefaultWebSecurityManager();
        sm.setRealm(realm);
        sm.setCacheManager(cacheManager);
        sm.setRememberMeManager(cookieRememberMeManager());
        sm.setSessionManager(sessionManager());
        return sm;
    }
    
    /**负责创建过滤器工厂,通过此工厂创建过滤器*/
    @Bean("shiroFilterFactory")
    public ShiroFilterFactoryBean newShirofFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean fBean = new ShiroFilterFactoryBean();
        fBean.setSecurityManager(securityManager);
        fBean.setLoginUrl("/doLoginUI");
        LinkedHashMap<String,String> filterMap = new LinkedHashMap<>();
        filterMap.put("/bower_components/**", "anon");
        ilterMap.put("/build/**", "anon");//anon表示允许匿名访问
        filterMap.put("/dist/**", "anon");
        filterMap.put("/plugins/**", "anon");
        filterMap.put("/user/doLogin","anon");
        filterMap.put("/doLogout","logout");
        filterMap.put("/**", "user");//authc表示要认证才可访问
        fBean.setFilterChainDefinitionMap(filterMap);
        return fBean;
    }
    
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
    /**
     * 基于此对象扫描Spring容器中所有Advisor对象,并借助底层
     * API为这些对象创建代理对象
     */

    @DependsOn("lifecycleBeanPostProcessor")
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        return new DefaultAdvisorAutoProxyCreator ();
    }

    /**
     * 此对象实现了Spring中的 Advisor(顾问)接口,此对象
     * 中要提供切入点.关联通知(Advice)对象进行功能扩展
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
        SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
 
    //CacheManager
    @Bean
    public CacheManager newCacheManager(){
        return new MemoryConstrainedCacheManager();
    }
 
    //RememberMe
    public CookieRememberMeManager cookieRememberMeManager() {
        CookieRememberMeManager rManager=new CookieRememberMeManager();
        SimpleCookie cookie=new SimpleCookie("rememberMe");
        cookie.setMaxAge(60*60);
        rManager.setCookie(cookie);
        return rManager;
    }
 
    //session manager
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sManager=new DefaultWebSessionManager();
        sManager.setGlobalSessionTimeout(60*60*1000);
        return sManager;
    }
}

 

2、Shiro过滤器

package com.kjyfx.common.config;

import javax.servlet.Filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.kjyfx.common.web.TimeAccessInterceptor;

@Configuration
public class SpringWebConfig implements WebMvcConfigurer{//相当于web.xml

    //配置spring mvc 拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加自定义拦截器,拦截成功后重定向到自定义页面
        registry.addInterceptor(new TimeAccessInterceptor())  
       .addPathPatterns("/user/doLogin");
    //自定义拦截器需要实现HandlerInterceptor接口,并重写preHandle方法
    //preHandle在控制层目标方法执行之前执行
    }
 
    @Bean
    public FilterRegistrationBean<Filter> newFilterRegistrationBean() {
        //创建过滤器注册器
        FilterRegistrationBean<Filter> rBean = new FilterRegistrationBean<>();
       //创建过滤器对象
       DelegatingFilterProxy filterProxy = new DelegatingFilterProxy("shiroFilterFactory");//与SpringShiroConfig中ShiroFactoryBean名相同
       rBean.setFilter(filterProxy);
       //配置过滤器映射路径
       rBean.addUrlPatterns("/*");
       return rBean;
    }
}

 

3、配置自定义Realm

如需认证,则需要继承AuthenticatingRealm,并重写doGetAuthenticationInfo认证方法进行认证;如需授权,则需继承AuthorizingRealm,并重写doGetAuthenticationInfo认证方法与doGetAuthorizationInfo授权方法

package com.kjyfx.service.realm;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.kjyfx.dao.SysMenuDao;
import com.kjyfx.dao.SysRoleMenuDao;
import com.kjyfx.dao.SysUserDao;
import com.kjyfx.dao.SysUserRoleDao;
import com.kjyfx.entity.SysUser;

@Service
public class ShiroUserRealm extends AuthorizingRealm{
    @Autowired
    private SysUserDao sysUserDao;
    @Autowired
    private SysUserRoleDao sysUserRoleDao;
    @Autowired
    private SysRoleMenuDao sysRoleMenuDao;
    @Autowired
    private SysMenuDao sysMenuDao;
 
    /**设定加密算法*/
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        //构建凭证匹配对象
        HashedCredentialsMatcher cMatcher = new HashedCredentialsMatcher();
        //设置加密算法
        cMatcher.setHashAlgorithmName("MD5");
        //设置加密次数
        cMatcher.setHashIterations(1);
        super.setCredentialsMatcher(cMatcher);
    }

    /**获取用户认证信息并封装返回*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
        AuthenticationToken token) throws AuthenticationException {
        //1.获取用户提交的身份信息
        UsernamePasswordToken upToken=(UsernamePasswordToken)token;
        String username=upToken.getUsername();
        //2.基于身份信息查询数据库用户
        SysUser user = sysUserDao.findUserByUserName(username);
       //3.判定用户是否存在
       if(user==null)
           throw new UnknownAccountException();
       //4.判定用户是否被禁用
       if(user.getValid()==0)
           throw new LockedAccountException();
       //5.封装用户信息并返回
       ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());
       SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
       user,//principal身份
       user.getPassword(),//hashedCredentials
       credentialsSalt,//credentialsSalt
       getName());//realmName
       return info;//返回给SecurityManager
    }
 
    /**获取授权信息并封装返回*/
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
        PrincipalCollection principals) {
        System.out.println("==doGetAuthorizationInfo==");
        //1.获取登录用户id
        SysUser user=(SysUser)principals.getPrimaryPrincipal();
        //2.基于用户id获取对应的角色并判断
        List<Integer> roleIds = sysUserRoleDao.findRoleIdsByUserId(user.getId());
        if(roleIds==null||roleIds.size()==0)
            throw new AuthorizationException();
        //3.基于角色id获取对应的菜单id并判断
        Integer array[]= {};
        List<Integer> menuIds = sysRoleMenuDao.findMenuIdsByRoleIds(roleIds.toArray(array));
        if(menuIds==null||menuIds.size()==0)
            throw new AuthorizationException();
        //4.基于菜单id获取对应的权限标识并判断
        List<String> permissions = sysMenuDao.findPermissions(menuIds.toArray(array));
        if(permissions==null||permissions.size()==0)
            throw new AuthorizationException();
        //5.封装结果并返回.
        Set<String> stringPermissions=new HashSet<>();
        for(String permission:permissions) {
            if(!StringUtils.isEmpty(permission)) {
                stringPermissions.add(permission);
            }
        }
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.setStringPermissions(stringPermissions);
        return info;//返回给授权管理器
    }
}

 

4、@Controller层

//登录认证
@RequestMapping("/user/doLogin")
public JsonResult doLogin(
    String username,
    String password,
    boolean isRememberMe) {
    //1.获取Subject对象(主体对象,负责提交用户信息)
    Subject subject=SecurityUtils.getSubject();
    //2.执行登录,提交用户信息
    //2.1封装用户信息
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    //2.2提交token(提交给SecurityManager)
    if(isRememberMe)token.setRememberMe(true);
    subject.login(token);
    return new JsonResult("login ok");
}

// 禁用启用
@RequestMapping("doValidById")
    public JsonResult doValidById(
    Integer valid,Integer id) {
    SysUser user = (SysUser)SecurityUtils.getSubject().getPrincipal();
    sysUserService.validById(valid, id,user.getUsername());
    return new JsonResult("update ok");
}

 

三、传统SSM整合Shiro(根据需要参考)

官网参考:http://shiro.apache.org/spring.html

1、web.xml中添加shiro过滤器

<!-- Shiro过滤器
此处的shiroFilter名要和applicationContext.xml中的shiro内置过滤器id名相同
-->
   <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>/*</url-pattern>
   </filter-mapping>

 

2、applicationContext.xml配置

①将Realm领域对象交给Spring管理(自定义Realm与上类似)

②将SecurityManager对象交给Spring管理

③将Shiro过滤器交给Spring管理

<!--配置自定义领域对象-->
<bean id="userRealm" class="com.kjyfx.config.UserRealm"></bean>

<!--配置安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
   <property name="realm" ref="userRealm"/>
</bean>

<!--配置shiro内置过滤器-->
   <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
       <property name="securityManager" ref="securityManager"/>
       <property name="loginUrl" value="/login.html"/>
       <property name="successUrl" value="/index.html"/>
       <!-- override these for application-specific URLs if you like:
       <property name="loginUrl" value="/login.jsp"/>
       <property name="successUrl" value="/home.jsp"/>
       <property name="unauthorizedUrl" value="/unauthorized.jsp"/> -->
       <!--<util:map>
               <entry key="anAlias" value-ref="someFilter"/>
           </util:map>
       </property> -->
   <!--对资源的访问权限控制-->
       <property name="filterChainDefinitions">
           <value>
               /login = anon
         /reg.html = anon
         /static/** = anon
         /user/doLogin = anon
         /user/doReg = anon
         /new = anon
         /authc = perms[admin]
               /** = authc
           </value>
       </property>
   </bean>

 

 

 

赞(1) 打赏
未经允许不得转载:所有资源由个人搜集整理自互联网,仅用于学习交流使用,请勿用于其他商业用途。如有侵权,请联系2448941602@qq.com删除科技云分享 » 『Java』Shiro权限认证框架的整合及相关配置
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

更多资源,尽在微信公众号【科技云分享】

关注公众号加入Q群

我叫科技云,感谢您的支持~

支付宝扫一扫打赏

微信扫一扫打赏