springboot集成shiro

springboot集成shiro

一:maven导入jar包

		<!-- shiro与Spring的集成包 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

二:创建一个自定义的Realm

在config中创建一个shiro的包,用于存放shiro相关的类,在里面创建一个名为MyRealm的类,内容如下:

package com.quyi.hello.config.shiro;

import com.quyi.hello.entity.User;
import org.apache.shiro.authc.*;
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 java.util.HashSet;
import java.util.Set;

/***
 * 这里使用假数据  真数据可以在这里导入Mapper对象从数据库中查询
 */
public class MyRealm extends AuthorizingRealm {

    /***
     * 权限--授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        String username = (String)principalCollection.getPrimaryPrincipal();
        //根据用户名查询角色 存入authorizationInfo
        Set<String> roles = new HashSet<>();
        roles.add("admin");
        roles.add("teacher");
        authorizationInfo.setRoles(roles);
        //根据用户名查询权限 存入authorizationInfo
        Set<String> per = new HashSet<>();
        roles.add("score:add");
        roles.add("score:delete");
        authorizationInfo.setStringPermissions(per);
        return authorizationInfo;
    }

    /***
     * 登录--认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取用户输入的用户名
        String uname = token.getPrincipal().toString();
        //创建假数据 模拟从数据库中取出来的信息
        User user = new User();
        user.setUsername("admin");
        user.setPassword("123");
        if(uname == null || "".equals(uname)){
            throw new AccountException("请输入用户名和密码");
        }
        //因为是模拟 所以这里表示数据库中查不到这个用户名 表示用户不存在
        if(!uname.equals(user.getUsername())){
            throw new UnknownAccountException("用户不存在");
        }
        //第一个参数传用户名或者user对象 第二个参数为数据库中取出来的密码 第三个为当前realm的名字
        return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
    }
}

在正式开发中,按照逻辑将假数据替换成数据库中查询即可

三:创建shiro的配置类

package com.quyi.hello.config.shiro;

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.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.context.annotation.DependsOn;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    
    /***
     * shiro过滤工厂
     * @param securityManager
     * @return
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        //并不是每次调用接口就会执行,而是调用需要操作码(permission)的接口就会执行
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login");//设置跳转的登录页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");//没有权限跳转的页面
        shiroFilterFactoryBean.setSuccessUrl("/index");
        Map<String, String> map = new LinkedHashMap<>();
        map.put("/login2", "anon");//登录接口放行
        //必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证
        map.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    /***
     * 注入安全管理器
     * @return
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
        defaultSecurityManager.setRealm(myRealm());//把我们自定义的realm放进去
        return defaultSecurityManager;
    }

    /***
     * 注入我们自定义的realm
     * @return
     */
    @Bean
    public MyRealm myRealm() {
        return new MyRealm();
    }
    
    /**
     * Shiro生命周期处理器
     *
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }
}

四:登陆接口

@PostMapping("/login2")
    public String login2(@RequestBody User user){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
        try {
            subject.login(token);
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("未知账户/没找到帐号");
            return "未知账户/没找到帐号";
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误");
            return "密码错误";
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("其他异常");
            return "其他异常" + e.getMessage();
        }
        return "登录成功";
    }

五:shiro四种权限控制方式

  1. URL拦截权限控制:基于filter过滤器实现

    在ShiroConfig配置文件中的shiroFilter方法中配置,如:
    在这里插入图片描述

  2. 注解控制

在这里插入图片描述

  1. 前端使用标签控制

在这里插入图片描述

  1. 代码级别权限控制
     public String edit(){ 
    
         Subject subject = SecurityUtils.getSubject();
         subject.checkPermission("staff-edit"); 
    
         Staff staff = staffService.findById(model.getId()); 
         staff.setName(model.getName()); 
         staff.setTelephone(model.getTelephone()); 
         staff.setHaspda(model.getHaspda()); 
         staff.setStandard(model.getStandard()); 
         staff.setStation(model.getStation()); 
         staffService.update(staff); 
         return LIST; 
     } 
    

配置好了权限控制后,就可以开始测试了。

六:shiro过滤工厂-参数讲解:

securityManager:这个属性是必须的。
loginUrl :没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面。
successUrl :登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此。
unauthorizedUrl :没有权限默认跳转的页面

七:shiro过滤器描述

anon:例子/admins/**=anon 没有参数,表示可以匿名使用。

authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数

roles(角色):例子/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。

perms(权限):例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。

rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。

port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString

是你访问的url里的?后面的参数。

authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证

ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https

user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查

八:shiro异常类

认证异常类

异常类描述
org.apache.shiro.authc.pam.UnsupportedTokenException身份令牌异常,不支持的身份令牌
org.apache.shiro.authc.UnknownAccountException未知账户/没找到帐号,登录失败
org.apache.shiro.authc.LockedAccountException帐号锁定
org.apache.shiro.authc.DisabledAccountException用户禁用
org.apache.shiro.authc.ExcessiveAttemptsException登录重试次数,超限。只允许在一段时间内允许有一定数量的认证尝试
org.apache.shiro.authc.ConcurrentAccessException一个用户多次登录异常:不允许多次登录,只能登录一次 。即不允许多处登录
org.apache.shiro.authc.AccountException账户异常
org.apache.shiro.authc.ExpiredCredentialsException过期的凭据异常
org.apache.shiro.authc.IncorrectCredentialsException错误的凭据异常
org.apache.shiro.authc.CredentialsException
org.apache.shiro.authc.AuthenticationException
凭据异常

权限异常类

异常类描述
org.apache.shiro.authz.HostUnauthorizedException
org.apache.shiro.authz.UnauthorizedException
没有访问权限,访问异常
org.apache.shiro.authz.UnauthenticatedException
org.apache.shiro.authz.AuthorizationException
授权异常
org.apache.shiro.ShiroExceptionshiro全局异常

orizedException
org.apache.shiro.authz.UnauthorizedException | 没有访问权限,访问异常 |
| org.apache.shiro.authz.UnauthenticatedException
org.apache.shiro.authz.AuthorizationException | 授权异常 |
| org.apache.shiro.ShiroException | shiro全局异常 |

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值