Shiro安全框架

Shiro

        Shiro是一款主流的Java安全框架,不依赖于任何容器,可以运行在JavaSE和JavaEE项目中,它的主要作用是对访问系统的用户进行身份认证,授权,会话管理,加密等操作

        Shiro是用来解决安全管理的系统化框架

Shiro核心组件

用户、角色、权限
权限赋予给角色,角色赋予给用户。如果用户的权限发生改变,则赋予用户新角色即可

UsernamePasswordToken: Shiro用来封装用户登录信息,使用用户的登录信息来创建令牌Token

SecurityManager: Shiro的核心部分,负责安全认证和授权

Suject: Shiro的一个抽象概念,包含了用户信息

Realm: 开发者自定义的模块,根据项目的需求,验证和授权的逻辑全部写在Realm中

AuthenticationInfo: 用户的角色信息集合,认证时使用

AuthorzationInfo: 角色的权限信息集合,授权时使用

DefaultWebSecurityDManager: 安全管理器,开发者自定义的Realm需要注入到DefaultWebSecurityDManager进行管理才能生效

ShiroFilterFactoryBean: 过滤器工厂,Shiro的基本运行机制是开发者定制规则,Shiro去执行,具体的执行操作就是由ShiroFilterFactoryBean创建的一个个Filter对象来完成

Shiro运行机制如下图
在这里插入图片描述

Spring Boot整合Shiro

1、引入Shiro依赖

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

2、自定义Shiro过滤器
在项目目录下创建realm(包) --> UserRealm.java,代码编写如下

package com.test.allstart.realm;

import com.test.allstart.entity.User;
import com.test.allstart.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 为用户创建token
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        // 通过token中的用户名去数据库中查找
        User user = userService.findByUsername(token.getUsername());
        if(user != null){
            // 判断密码是否正确
//            return new SimpleAuthenticationInfo(user,user.getPassword(),user.getUserName());
            return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
        }
        return null;
    }
}

3、Shiro配置类
在config目录下新建文件ShiroConfig.java文件,配置类代码如下

package com.test.allstart.config;

import com.test.allstart.realm.UserRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Shiro 配置类
 */
@Configuration
public class ShiroConfig {

    /**
     * 参数信息解释见第二个函数
     * @param defaultWebSecurityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(defaultWebSecurityManager);
        return factoryBean;
    }

    /**
     * 定义此函数作用是开发者自定义的Realm需要注入到DefaultWebSecurityDManager进行管理才能生效
     * @param userRealm 因为 UserRealm 已经在IOC容器中,所以可以直接在函数参数中写,在函数中可
     *                  以直接从IOC容器中读取 UserRealm。@Qualifier("userRealm")的作用是指定
     *                  一个名字,在IOC容器中通过名字去寻找
     * @return
     */
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(userRealm);
        return manager;
    }

    /**
     * 将写的规则注入到IOC容器中
     * @return
     */
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }
}

4、编写认证和授权规则
Shiro已经写好,我们只需要从中进行选择即可

  • 认证过滤器

    • anon:无需认证
    • authc:必须认证
    • authcBasic:需要通过HTTPBasic认证
    • user:不一定通过认证,只要曾经被Shiro记录即可,
  • 授权过滤器

    • perms:必须拥有某个权限才能访问
    • role:必须拥有某个角色才能访问
    • port:请求的端口必须是指定值才可以
    • rest:请求必须基于RESTful,POST、PUT、GET、DELETE
    • ssl:必须是安全的URL请求,协议是HTTPS

创建3个页面,main.html、manager.html、administrator.html
访问权限如下:
1、必须登录才能访问main.html
2、当前用户必须拥有manager授权才能访问 manager.html
3、当前用户必须拥有 administrator角色才能访问 administrator.html

认证

在ShiroConfig配置类中的shiroFilterFactoryBean()方法中加入如下代码

@Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(defaultWebSecurityManager);

        // 权限设置
        Map<String,String> map = new HashMap<>();
        map.put("/main","authc");                       // 当访问main.html页面时,必须要认证(authc)
        map.put("/manager","perms[manager]");           // 当访问manager.html页面时,必须是manager权限
        map.put("/administrator","roles[administrator]"); // 当访问administrator.html页面时,必须是administrator角色
        factoryBean.setFilterChainDefinitionMap(map);

        // 设置登录页面
        factoryBean.setLoginUrl("/login");
        return factoryBean;
    }

同时在Controller层中编写如下代码

@GetMapping("/{url}")
public String redirect(@PathVariable("url") String url){
    return url;
}

@PostMapping("/login")
public String login(String username, String password, Model model){
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(username,password);
    try{
        subject.login(token);
        return "index";
    } catch (UnknownAccountException e){        // 捕获用户名错误的信息
        e.printStackTrace();
        model.addAttribute("msg", "用户名错误!");
        return "login";
    } catch (IncorrectCredentialsException e ){ // 捕获用户密码错误的信息
        e.printStackTrace();
        model.addAttribute("msg", "密码错误!");
        return "login";
    }
}

5、设置未授权访问返回的页面

// 在ShiroConfig页面的shiroFilterFactoryBean()函数中添加如下代码
// 设置未授权页面
factoryBean.setUnauthorizedUrl("/unauth");

// 在controller层添加如下代码
@GetMapping("/unauth")
@ResponseBody
public String authun(){
    return "未授权,无法访问";
}

//启动程序,当没有manager权限的用户访问manager.html页面时,浏览器页面将显示“未授权,无法访问”

6、设置用户注销退出

// Controller层中加入代码
@GetMapping("/logout")
public String logout(){
    Subject subject = SecurityUtils.getSubject();
    subject.logout();
    return "login";
}

// 前端页面加入代码
<div th:if="${session.user != null}">
    <span th:text="${session.user.userName} + '欢迎回来'"></span> | <a href="/logout"> 退出</a>
</div>

Shiro整合thymeleaf

1、pom.xml文件中引入依赖

<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>

2、配置类中加入ShiroDialect

@Bean
public ShiroDialect shiroDialect(){
    return new ShiroDialect();
}

3、前端页面index中添加代码
添加引入

<html lang="en" xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">

添加shiro标签

<a href="/main">main</a>
<!--    设置权限   -->
<div shiro:hasPermission="admin">
    <a href="/manager">manager</a>
</div>
<!--    设置角色   -->
<div shiro:hasRole="ace">
    <a href="/administrator">administrator</a>
</div>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值