什么是shiro安全框架,以及在springboot中如何使用

Posted lovoo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是shiro安全框架,以及在springboot中如何使用相关的知识,希望对你有一定的参考价值。

一、 概述

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

  • 其中 SecurityManager是核心,相当于Spring MVC的前端控制器,起管家调度作用。
  • Subject可以理解为账户。来验证其是否合法或者权限。
  • Realms可以理解为数据源,即程序从Realm中拿数据来确认该用户时候是合法,权限等。Realm可以自己实现,继承Realm即可。下面这个例子默认Realm的来源为ini配置文件,即zhang=123
    wang =123.符合这两个即ok.

二、作用与总结

  1. shiro 主要就是对访问系统需要对系统授权 和认证;他专门有一个安全管理器, 这个安全管理器包含授权器和认证器,方法授权和认证都是通过这两个方法;
  2. sessionmanager session 管理器 一般单点登录就是这样设置的。
  3. cache管理器,主要是将授权缓存起来, 一般shiro通过数据库交互都是通过realm存储授权与逻辑判断:比如判断当前角色有哪些权限,Realm实质上是一个安全相关的DAO。
  4. shiro的角色是动态创建的,一般是一个角色对应一组权限,这样就非常灵活。
  5. 说道安全框架肯定离不开密码。 shiro拥有密码管理器与密码加密加盐等等一些列对用户加密的操作。

三、在SpringBoot项目中集成

  1. 首先引入依赖,
  2. 然后继承AuthorizingRealm实现权限认证与授权,
  3. 再配置缓存与Cookie,
  4. 登录时进行密码验证

1、引入相关依赖

  <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.6.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-ehcache</artifactId>
        <version>1.6.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
        <version>1.6.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.6.0</version>
    </dependency>

2、UserRealm相关代码

@Component
@Slf4j
public class UserRealm extends AuthorizingRealm {

    // 在shiro框架中(UserRealm)使用过@Autowire注入的类,缓存注解和事务注解都失效。
    // 解决方法:
    // 1.在Shiro框架中注入Bean时,不使用@Autowire,使用ApplicationContextRegister.getBean()方法,手动注入bean。保证该方法只有在程序完全启动运行时,才被注入。
    // 2.使用@Autowire+@Lazy注解,设置注入到Shiro框架的Bean延时加载(即在第一次使用的时候加载)。
   
    @Lazy
    @Autowired
    private UserService userService;
    @Lazy
    @Autowired
    private MenuService menuService;

    /**
     * 授权(验证权限时调用)
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        User user = (User)principals.getPrimaryPrincipal();
        String userId = user.getId();
        String username = user.getUsername();

        Session session = ShiroUtil.getSession();
        Set<String> rolesSet = (Set<String>) session.getAttribute("rolesSet");
        Set<String> permsSet = (Set<String>) session.getAttribute("permsSet");
        session.setAttribute("user", user);
        session.setAttribute("username", username);
       
        List<String> permsList = menuService.getPermission(userId);

        //用户权限列表
        if (CollectionUtils.isEmpty(permsSet)) {
            permsSet = new HashSet<String>();
            for(String perms : permsList){
                if(StrUtil.isBlank(perms)){
                    continue;
                }
                permsSet.addAll(Arrays.asList(perms.trim().split(",")));
            }
            session.setAttribute("permsSet", permsSet);
        }
        if (CollectionUtils.isEmpty(rolesSet)) {
            rolesSet = userService.listUserRoles(userId);
            session.setAttribute("rolesSet", rolesSet);
        }

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //设置权限
        info.setStringPermissions(permsSet);
        //设置角色
        info.setRoles(rolesSet);
        return info;
    }

    /**
     * 认证(登录时调用)
     * @param authcToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        MyUsernamePasswordToken token = (MyUsernamePasswordToken)authcToken;

        //门店编号
        String storeCode = token.getStoreCode();
        if(StrUtil.isEmpty(storeCode)){
            throw new UnknownAccountException("请输入门店号!");
        }

        //查询用户信息
//        User user = userService.getByUsername(token.getUsername());
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("store_code", storeCode);
        wrapper.eq("username", token.getUsername());
        wrapper.eq("IFNULL(status, 1)", 1);
        User user = userService.getOne(wrapper);
        //账号不存在
        if(user == null) {
            throw new UnknownAccountException("账号或密码不正确!");
        }

        String password = CryptionKit.genUserPwd(new String((char[]) token.getCredentials()));
        if (!user.getPassword().equals(password)) {
            // 密码错误
            throw new IncorrectCredentialsException("账号或密码不正确!");
        }

        if (user.getStatus() != SysConstant.VALID_USER) {
            // 账号锁定
            throw new LockedAccountException("账号已被锁定,请联系管理员!");
        }

        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }

    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();
        shaCredentialsMatcher.setHashAlgorithmName(ShiroUtil.HASH_ALGORITHM_NAME);
        shaCredentialsMatcher.setHashIterations(ShiroUtil.HASH_ITERATIONS);
        super.setCredentialsMatcher(shaCredentialsMatcher);
    }


    /**
     * 自定义方法:清除所有 授权缓存
     */
    public void clearAllCachedAuthorizationInfo() {
        if(getAuthorizationCache() != null){
            getAuthorizationCache().clear();
        }

    }

    /**
     * 自定义方法:清除所有 认证缓存
     */
    public void clearAllCachedAuthenticationInfo() {
        if(getAuthenticationCache() != null){
            getAuthenticationCache().clear();
        }
    }

    /**
     * 自定义方法:清除所有的  认证缓存   授权缓存
     */
    public void clearAllCache() {

        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();

        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        super.clearCache(principals);
    }

}

3、配置缓存与Cookie

@Configuration
public class ShiroConfig {


    @Bean
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 集成缓存
     *
     * @return sessionManager
     */
    @Bean("sessionManager")
    public SessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        //设置session过期时间(单位:毫秒),默认为15分钟
        sessionManager.setGlobalSessionTimeout(10000 * 60 * 1500);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(false);

        return sessionManager;
    }

    /**
     * 1.配置Cookie对象
     * 记住我的cookie:rememberMe
     *
     * @return SimpleCookie rememberMeCookie
     */
    @Bean
    public SimpleCookie rememberMeCookie() {
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //simpleCookie.setHttpOnly(true);
        //单位()1
        simpleCookie.setMaxAge(60 * 60 * 24);
        return simpleCookie;
    }

    /**
     * 2.配置cookie管理对象
     *
     * @return CookieRememberMeManager
     */
    @Bean
    public CookieRememberMeManager cookieRememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return cookieRememberMeManager;
    }

    @Bean("securityManager")
    public SecurityManager securityManager(UserRealm userRealm, SessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        // 自定义缓存实现
        securityManager.setCacheManager(ehCacheManager());
        securityManager.setSessionManager(sessionManager);
        // 设置cookie管理
        securityManager.setRememberMeManager(cookieRememberMeManager());
        return securityManager;
    }


    /**
     * shiro缓存管理器。需要添加到securityManager中
     * @return cacheManager
     */
    @Bean
    public EhCacheManager ehCacheManager() {
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:shiro/ehcache-shiro.xml");
        return cacheManager;
    }



    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);

        /*重要,设置自定义拦截器,当访问某些自定义url时,使用这个filter进行验证*/
        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
        // 如果map里面key值为authc,表示所有名为authc的过滤条件使用这个自定义的filter
        // map里面key值为LoginFilter,表示所有名为LoginFilter的过滤条件使用这个自定义的filter,具体见下方
        filters.put("myFilter", new LoginFilter());
        shiroFilter.setFilters(filters);

        shiroFilter.setLoginUrl("/login");
//        shiroFilter.setSuccessUrl("/sys/index");
        shiroFilter.setUnauthorizedUrl("/403");

        Map<String, String> filterMap = new LinkedHashMap<String, String>();
        filterMap.put("/vue-admin-template/**", "anon");
        filterMap.put("/templates/test/**", "anon");
        filterMap.put("/base/product/**", "anon");
        filterMap.put("/static/**", "anon");
        filterMap.put("/login/**", "anon");
        filterMap.put("/logout", "logout");
        filterMap.put("/druid/**", "anon");
        filterMap.put("/captcha.jpg", "anon");
        filterMap.put("/pay/wx/notify", "anon");
        filterMap.put("/pay/wx/notifyRefund", "anon")Shiro安全框架简介以及身份验证

简单易用的Apache shiro框架,以及复杂完整的springboot security安全框架

安全框架 - Shiro与springMVC整合的注解以及JSP标签

shiro安全框架-用户认证授权以及权限控制

Shiro 权限框架使用总结

安全框架Shiro和SpringSecurity的比较