springboot整合shiro安全框架(超详细)新手必看

自己第一次搞shiro的时候看了很多博客,做的时候还是一知半解的,也不能说别人的写的不好,可能自己领悟的比较慢,有些细节需要自己去思考,以至于花费的时间有点多,但也不都是坏处,这样有助于我们理解的更深刻。这篇文章希望可以帮助大家更快的完成spring集成shiro

工具

IntelliJ IDEA
关于怎么新建一个springboot项目我这里就不赘述了,不懂的小伙伴可以先看一下这篇博客idea从零新建springboot项目

第一步:

既然我们有了springboot项目,接下来第一步就是要引入shiro的依赖

Maven配置:

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

关于怎么引入依赖以防万一我还是提一句为好,先贴出我的项目结构
引入依赖就是在pom.xml文件中加上上述maven配置的几行代码。pom.xml就是maven用来管理项目依赖的文件。

第二步:

springboot整合shiro只需要两个类,一个是ShiroConfig类,一个是CustomRealm类。当我们引入shiro所需的jar包后我们就可以开始第二步,那就是配置ShiroConfig类。
关于ShiroConfig类是什么:
没错这个类就是关于shiro的一些配置。包括过滤的文件和权限,密码加密的算法,其用注解等相关功能。
ShiroConfig类的配置:

package com.enlistentype.config;

import com.enlistentype.shiro.CustomRealm;
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.mgt.SecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
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;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Cyy
 * @date 2020/2/14 12:22
 */

@Configuration
public class ShiroConfig {

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean (SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

		//设置登录,成功,权限不足跳转页面
        shiroFilterFactoryBean.setLoginUrl("/ltLogin");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");

        Map<String, String> map = new HashMap<>();
        <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都可以匿名访问-->
        map.put("/ltLogin/subLogin", "anon");
        map.put("/**", "anon");
        map.put("/admin/**", "authc");
        map.put("/user/**", "authc");
		
		//设置url,需要认证或者直接通过
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    //将自定义验证方式加入容器
    @Bean
    public CustomRealm myShiroRealm() {
        CustomRealm customRealm = new CustomRealm();
        return customRealm;
    }

    //权限管理,配置Realm的管理认证
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(myShiroRealm());
        return defaultWebSecurityManager;
    }
}

一般就只需要这三个方法,方法也不复杂,注释也都写好了。
ShiroFilterFactoryBean方法:
就是shiro的过滤器,可以设置登录,权限不足跳转页面等。默认的过滤器还有:anno、authc、authcBasic、logout、noSessionCreation、perms、port、rest、roles、ssl、user过滤器。
具体的大家可以查看package org.apache.shiro.web.filter.mgt.DefaultFilter。这个类,常用的也就authc、anno。
securityManager方法:
这个方法主要是要设置项目的安全管理器,因为这里是一个web项目,所以我们使用的是DefaultWebSecurityManager,然后设置realm为自定义realm。这里还会有一个坑我们要注意,就是有时候会报错没有找到securityManager类,很有可能是系统自动导入的包是错误的,不是shiro的security包
CustomRealm方法:
将 customRealm的实例化,当然这里也可以利用注解的方式去注入。

第三步:

配置好ShiroConfig类后就是配置CustomRealm类了。
CustomRealm配置:

package com.enlistentype.shiro;

import com.enlistentype.common.Result;
import com.enlistentype.feignclient.FeignClientProxy;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author Cyy
 * @date 2020/2/15 14:32
 */

@Component
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    protected FeignClientProxy feignClientProxy;

	//重写授权方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) principalCollection.getPrimaryPrincipal();

        //使用远程方法获取主体的角色和权限
        Result RoleNameOfUser =  feignClientProxy.getRoleNamesOfUser(username);
        Result PermissionOfUser = feignClientProxy.getPermissionString(username);

        //打印获得的角色与权限
        System.out.println(RoleNameOfUser.getData().get("roleSet"));
        System.out.println(PermissionOfUser.getData().get("permissionSet"));

        //将获得的角色与权限转换为set集合以便给setRole赋值
        Set<String> role = new HashSet<String>((Collection<? extends String>) RoleNameOfUser.getData().get("roleSet"));
        Set<String> permission = new HashSet<String>((Collection<? extends String>) PermissionOfUser.getData().get("permissionSet"));

        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(role);
        simpleAuthorizationInfo.setStringPermissions(permission);

        return simpleAuthorizationInfo;
    }

	//重写认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		//获取用户名
        String username = (String) authenticationToken.getPrincipal();
		//通过用户名获取密码
        String password = getPasswordByUserName(username);
        if (password == null) {
            return null;
        }
        //构建认证信息
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, "customRealm");

        return simpleAuthenticationInfo;
    }

    private String getPasswordByUserName(String username) {
        return userMap.get(username);
    }
	//模拟数据库获取用户密码
    Map<String, String> userMap = new HashMap<>();

    {
        userMap.put("James2", "123456");

        super.setName("customRealm");
    }
}

这个类也很简单,就是重载认证和授权的方法,首先都是通过subject获取用户名,我上面的map主要是模拟数据库获取用户信息,实际项目换成数据库查询操作即可。

最后一步:

到这里springboot整合shiro可以说是大功告成了,赶紧去写个controller测试一下吧。至于controller就是写一个登录逻辑,获取url的用户名和密码参数,封装成token,再subject.login(token)一下,可以在控制台打印是否认证成功。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值