springboot 配置 shiro

本文详细介绍了如何在SpringBoot项目中集成Shiro进行权限管理,包括引入依赖、自定义Realm、配置Shiro、编写Controller进行测试以及处理无权限访问的异常。适合初学者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、引入 shiro 的包

二、自定义 realm 

三、shiro 配置

四、写一个 controller 测试

五、无权限的时候直接报错的错误方式


前提:

先准备一个 springboot+mybatis 的环境:https://blog.youkuaiyun.com/weidong_y/article/details/81709391

一、引入 shiro 的包

<!-- shiro 配置 -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.3.2</version>
</dependency>

二、自定义 realm 

MyShiroRealm.java

package com.yyzheng.oa.shiro;

import com.yyzheng.oa.dao.User;
import com.yyzheng.oa.service.PermissionService;
import com.yyzheng.oa.service.RoleService;
import com.yyzheng.oa.service.UserService;
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.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class MyShiroRealm extends AuthorizingRealm {
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private UserService userService;

    // 角色权限和对应权限添加
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取登录用户名
        String userName = (String)principalCollection.getPrimaryPrincipal();
        // 查询用户的角色信息
        Set<String> roles = getRolesByUsername(userName);
        // 查询角色的权限信息
        Set<String> permissions = getPermissionsByUserName(userName);
        // 设置用户的角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roles);
        simpleAuthorizationInfo.setStringPermissions(permissions);

        return simpleAuthorizationInfo;
    }

    // 根据用户名字从数据库中获取当前用户的权限数据
    private Set<String> getPermissionsByUserName(String userName) {
        List<String> list = permissionService.queryPermissionNameByUserName(userName);
        if( list != null ){
            Set<String> sets = new HashSet<>(list);
            return sets;
        }else{
            return null;
        }
    }

    // 根据用户名字从数据库中获取当前用户的角色数据
    private Set<String> getRolesByUsername(String userName) {
        List<String> list = roleService.queryRoleNameByUsername(userName);
        if( list != null ){
            Set<String> sets = new HashSet<>(list);
            return sets;
        }else{
            return null;
        }
    }

    // 认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 1.从主体传过来的信息中获取用户名
        String userName = (String)authenticationToken.getPrincipal();
        // 2.通过用户名到数据库获取凭证
        String password = getPasswordByUserName(userName);
        if( password == null ){
            return  null;
        }
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName,password,"myShiroRealm");
        return simpleAuthenticationInfo;
    }

    // 通过用户名从数据库中获取当前用户的密码
    private String getPasswordByUserName(String userName) {
        User user = userService.queryUserByUserName(userName);
        if( user != null ){
            return user.getPassword();
        }else{
            return null;
        }
    }

}

三、shiro 配置

package com.yyzheng.oa.config;

import com.yyzheng.oa.exception.MyExceptionResolver;
import com.yyzheng.oa.shiro.MyShiroRealm;
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.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;

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

@Configuration
public class ShiroConfiguration {

    // 创建自定义 realm
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }

    // 创建 SecurityManager 对象
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    // Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> map = new HashMap<>();
        // 登出
        map.put("/logout", "logout");
        // 对所有用户认证
        map.put("/**", "authc");
        // 对登录跳转接口进行释放
        map.put("/subLogin", "anon");
        map.put("/err", "anon");
        // 登录
        // 注意:这里配置的 /login 是指到 @RequestMapping(value="/login")中的 /login
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 首页
        shiroFilterFactoryBean.setSuccessUrl("/index");
        // 错误页面,认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/err");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    // 加入注解的使用,不加这个,注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    // 跟上面的注解配置搭配使用,有时候加了上面的配置后注解不生效,需要加入下面的配置
    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator app = new DefaultAdvisorAutoProxyCreator();
        app.setProxyTargetClass(true);
        return app;
    }

}

四、写一个 controller 测试

@Controller
public class UserController {

    @RequestMapping(value = "/login")
    public String login(){
        return "/login";
    }

    @RequestMapping(value = "/err")
    public String err(){
        return "/err";
    }

    @RequestMapping(value = "/subLogin")
    public String subLogin(User user){
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
        try{
            subject.login(token);
        }catch (AuthenticationException e){
            e.printStackTrace();
            return e.getMessage();
        }
        return "success";
    }

    @RequiresRoles(value = "admin")
    @RequestMapping(value = "/test")
    @ResponseBody
    public String test(){
        return  "123";
    }
}

五、无权限的时候直接报错的错误方式

自定义一个异常拦截,自定义跳转页面。

MyExceptionResolver.java 拦截下异常。

package com.yyzheng.oa.exception;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

public class MyExceptionResolver implements HandlerExceptionResolver{

    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("==============异常开始=============");
        //如果是shiro无权操作,因为shiro 在操作auno等一部分不进行转发至无权限url
        if(ex instanceof UnauthorizedException){
            // 跳转到 templates 文件下面找 err.html 页面
            ModelAndView mv = new ModelAndView("err");
            return mv;
        }
        ex.printStackTrace();
        ModelAndView mv = new ModelAndView("err");
        mv.addObject("exception", ex.toString().replaceAll("\n", "<br/>"));
        return mv;
    }
}

在shiro中配置一下:

// 自定义异常捕获注册
    @Bean
    public HandlerExceptionResolver solver(){
        HandlerExceptionResolver handlerExceptionResolver = new MyExceptionResolver();
        return handlerExceptionResolver;
    }

 

为了配置Spring BootShiro,您需要执行以下步骤: 1. 在您的Spring Boot项目中,使用Maven或Gradle将Shiro依赖项添加到您的构建配置文件中。例如,对于Maven,请在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.7.1</version> </dependency> ``` 2. 创建一个Shiro配置类,该类将包含Shiro的相关配置。您可以在该类中定义身份验证和授权规则等配置。例如,创建一个名为ShiroConfig的类,并使用@Configuration注解将其标记为配置类。 ```java @Configuration public class ShiroConfig { // 配置身份验证规则 @Bean public Realm realm() { // 实现自己的Realm } // 其他配置... } ``` 3. 在Shiro配置类中创建一个Realm bean,并在其中实现自己的Realm。Realm负责验证用户身份和进行授权。您可以使用现有的Realm实现,如JdbcRealm或IniRealm,也可以实现自定义的Realm。 例如,创建一个名为MyRealm的类,并实现`org.apache.shiro.realm.AuthorizingRealm`接口来实现您自己的Realm逻辑。 ```java public class MyRealm extends AuthorizingRealm { // 身份验证逻辑 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 实现身份验证逻辑 } // 授权逻辑 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 实现授权逻辑 } // 其他方法... } ``` 4. 在Shiro配置类中,通过@Bean注解将自定义的Realm bean注入到容器中。 5. 在application.properties或application.yml文件中配置Shiro的相关属性。您可以设置身份验证的URL、登录URL、注销URL等。例如,在application.yml文件中添加以下配置: ```yaml shiro: loginUrl: /login successUrl: /home unauthorizedUrl: /unauthorized ``` 这些是配置Shiro的基本步骤。您还可以根据您的应用程序需求添加其他配置和功能。请注意,这只是一个简单的示例,您可能需要根据自己的情况进行调整和扩展。 希望以上信息对您有所帮助!如果您有任何进一步的问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值