Spring Boot(九)整合 Shiro

<!--集成shiro安全框架-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
</dependency>

Shiro 配置类

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        System.out.println("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        /*拦截器*/
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        /*配置不会被拦截的链接 顺序判断*/
        /*anon:所有url都都可以匿名访问*/
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/templates/**", "anon");
        /*配置退出*/
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/index", "anon");
        /*过滤链定义,从上向下顺序执行,一般将/**放在最为下*/
        /*authc:所有url都必须认证通过才可以访问-->*/
        filterChainDefinitionMap.put("/**", "authc");
        /*如果不设置默认会自动寻找Web工程根目录下的"/login"页面*/
        shiroFilterFactoryBean.setLoginUrl("/index");
        /* 登录成功后要跳转的链接*/
        shiroFilterFactoryBean.setSuccessUrl("/userInfo");
        /*未授权界面*/
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 凭证匹配器(由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了)
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(2000);//散列的次数,比如散列两次,相当于 md5(md5(""));
        return hashedCredentialsMatcher;
    }

    @Bean
    public ShiroRealm myShiroRealm(){
        ShiroRealm myShiroRealm = new ShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myShiroRealm;
    }

    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    /**
     *  开启shiro aop注解支持.
     *  使用代理方式;所以需要开启代码支持;
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean(name="simpleMappingExceptionResolver")
    public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
        Properties mappings = new Properties();
        mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
        mappings.setProperty("UnauthorizedException","403");
        r.setExceptionMappings(mappings);  // None by default
        r.setDefaultErrorView("error");    // No default
        r.setExceptionAttribute("ex");     // Default is "exception"
        r.setWarnLogCategory("example.MvcLogger");     // No default
        return r;
    }
}

ShiroRealm

public class ShiroRealm extends AuthorizingRealm{
   @Autowired
    private ISysUserService iSysUserService; //用户
    @Autowired
    private ISysRoleService iSysRoleService; //角色
    @Autowired
    private ISysRoleMenuService iSysRoleMenuService;//角色-菜单
    @Autowired
    ISysMenuPermissionsService iSysMenuPermissionsService;//菜单-权限

    /*权限授权*/
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.info("pc权限授权");
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //用户
        SysUser sysUser = (SysUser) super.getAvailablePrincipal(principals);
        QueryWrapper<SysRole> sysRoleQueryWrapper = new QueryWrapper<>();
        sysRoleQueryWrapper.eq("idsys_role",sysUser.getSysRoleIdsysRole());
        //角色
        List<SysRole> sysRoleList = iSysRoleService.list(sysRoleQueryWrapper);
        for (SysRole sysRole : sysRoleList) {
            simpleAuthorizationInfo.addRole(sysRole.getSysRoleName());
            //角色-菜单
            QueryWrapper<SysRoleMenu> roleMenuQueryWrapper=new QueryWrapper<>();
            roleMenuQueryWrapper.eq("sys_role_menu_roleId",sysUser.getSysRoleIdsysRole());
            List<SysRoleMenu> SysRoleMenuList =  iSysRoleMenuService.list(roleMenuQueryWrapper);
            for (SysRoleMenu sysRoleMenu:SysRoleMenuList) {
                //菜单-权限 shirokey
                QueryWrapper<SysMenuPermissions> sysMenuPermissionsQueryWrapper = new QueryWrapper<>();
                sysMenuPermissionsQueryWrapper.eq("sys_menu_permissions_menuId",sysRoleMenu.getSysRoleMenuMenuid());
                List<SysMenuPermissions> sysMenuPermissionsList = iSysMenuPermissionsService.list(sysMenuPermissionsQueryWrapper);
                for (SysMenuPermissions sysMenuPermissions : sysMenuPermissionsList) {
                    if(!CheckUtil.isNull(sysMenuPermissions.getSysMenuPermissionsShirokey())) {
                        //simpleAuthorizationInfo.setStringPermissions(sysMenuList);
                        simpleAuthorizationInfo.addStringPermission(sysMenuPermissions.getSysMenuPermissionsShirokey());//添加权限标识
                    }
                }
            }
        }
        return simpleAuthorizationInfo;
    }

    /*登录认证*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        log.info("pc登录认证");
        //获取用户的输入的账号.
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String username = usernamePasswordToken.getUsername();
        String password = String.valueOf(usernamePasswordToken.getPassword());

        //根据用户名查询,用户名必须是唯一
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sys_user_name", username);
        SysUser sysUser = iSysUserService.getOne(queryWrapper);

        //校验密码
        //加密方式
        String algorithmName = "MD5";
        //加密次数
        int hashIterations = 2000;
        //加密盐值 username作为颜值必须为唯一值 注册时需要注意
        Object salt = ByteSource.Util.bytes(sysUser.getSysUserName());;
        /*md5Result:9ec808d39c36c800591f1ee14f5f3175*/
        String md5Result = new SimpleHash(algorithmName, password, salt, hashIterations).toHex();
        //判断用户密码是否正确,状态等
        if (sysUser != null) {
            if (md5Result.equals(sysUser.getSysUserPassword())) {
                /*session用户*/
                Session session = Jurisdiction.getSession();
                session.setAttribute(username + Const.SESSION_USER,sysUser);
                /*通过身份验证*/
                /*principal:认证信息,可以是username,也可以是整个实体*/
                Object principal = sysUser;
                /*credentials:密码*/
                Object credentials = sysUser.getSysUserPassword();
                /*credentialsSalt:盐值*/
                ByteSource credentialsSalt = ByteSource.Util.bytes(sysUser.getSysUserName());
                /*realmName:当前realm对象的name,调用父类getName()*/
                String realmName = getName();

                SimpleAuthenticationInfo simpleAuthorizationInfo  = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
                return simpleAuthorizationInfo;
            }
        }
        return null;
    }
}

Controller

@Slf4j
@Controller
public class HomeController{

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private TUserMapper tUserMapper;

    @RequestMapping({"/","/index"})
    public String index(){

        Wrapper<UserInfo> wrapper=new QueryWrapper<>();
        ((QueryWrapper<UserInfo>) wrapper).eq("user_name","admin");

        UserInfo userInfo = userInfoMapper.selectOne(wrapper);
        log.info(userInfo.toString());
        return"/login";
    }

    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String login(HttpServletRequest request, @RequestParam Map<String, Object> map) throws Exception{
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "123");
        Subject subject = SecurityUtils.getSubject();
        String msg = "";
        try {
            subject.login(token);
        } catch (IncorrectCredentialsException ice) {
            msg = "捕获密码错误异常";
        } catch (UnknownAccountException uae) {
            msg = "捕获未知用户名异常";
        } catch (ExcessiveAttemptsException eae) {
            msg = "重复多次登录";
        }

        map.put("msg", msg);
        // 此方法不处理登录成功,由shiro进行处理
        return "/userInfo";
    }

    @RequestMapping("/403")
    public String unauthorizedRole(){
        System.out.println("------没有权限-------");
        return "403";
    }

    @RequiresPermissions("userInfo")
    @RequestMapping("/userInfo")
    public String userInfo(){
//        Subject subject = SecurityUtils.getSubject();
//        subject.hasRole("user");
        return "userInfo";
    }
    @RequiresPermissions("userInfoAdd")
    @RequestMapping("/userInfoAdd")
    public String userInfoAdd(){
        return "userInfoAdd";
    }

    @RequestMapping("/userInfoDel")
    public String userInfoDel(){
        return "userInfoDel";
    }

}

**大功告成,下面是演示 **
http://127.0.0.1:9001/index
在这里插入图片描述
在这里插入图片描述
返回通过身份验证的simpleAuthorizationInfo,登录成功
在这里插入图片描述
访问 http://127.0.0.1:9001/userInfo
authorizationInfo.addStringPermission(“userInfoAdd”);
因为只加了authorizationInfo只加了 userInfoAdd 权限,没有 addStringPermission(“userInfo”);
而userInfo方法 又加了 @RequiresPermissions(“userInfo”)

所以只会跳转到 403 页面
在这里插入图片描述
在这里插入图片描述
访问 http://127.0.0.1:9001/userInfoAdd
authorizationInfo.addStringPermission(“userInfoAdd”);
userInfoAdd 又加了 @RequiresPermissions(“userInfoAdd”)

所以只跳转到 userInfoAdd 页面
在这里插入图片描述
请求都会进入 doGetAuthorizationInfo 进行权限校验
在这里插入图片描述
没有
@RequiresPermissions("请求)
或者
Subject subject = SecurityUtils.getSubject();
subject.hasRole(“user”);

则视为无须权限
http://127.0.0.1:9001/userInfoDel
也可以访问
且无需进入 doGetAuthorizationInfo
在这里插入图片描述
当我们登录成功后,其他操作
Request.Headers
将自动带上凭证
Cookie: JSESSIONID=ABD4BED200D6ACF452AB2373F916C93D
在这里插入图片描述
一个简单的微服务网站就搭建成功了。配合 Mubatis-Plus 使用,其他就是业务 上的问题了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神奇的网友

day day up

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值