SpringBoot集成Shiro權限控制【親測可用】

Shiro是一個強大的簡單易用的Java安全框架,主要用來更便捷的認證,授權,加密,會話管理。Shiro首要的和最重要的目標就是容易使用並且容易理解。

Shiro基本概念

三個核心組件:Subject, SecurityManager 和 Realms.

  • Subject:翻譯爲主角,當前參與應用安全部分的主角。可以是用戶,可以試第三方服務,可以是cron 任務,或者任何東西。主要指一個正在與當前軟件交互的東西。所有Subject都需要SecurityManager,當你與Subject進行交互,這些交互行爲實際上被轉換爲與SecurityManager的交互

Subject代表了當前用戶的安全操作,SecurityManager則管理所有用戶的安全操作。

  • SecurityManager:安全管理員,Shiro架構的核心,它就像Shiro內部所有原件的保護傘。然而一旦配置了SecurityManager,SecurityManager就用到的比較少,開發者大部分時間都花在Subject上面。
    請記得,當你與Subject進行交互的時候,實際上是SecurityManager在背後幫你舉起Subject來做一些安全操作。

  • Realms:Realms作爲Shiro和你的應用的連接橋,當需要與安全數據交互的時候,像用戶賬戶,或者訪問控制,Shiro就從一個或多個Realms中查找。Shiro提供了一些可以直接使用的Realms,如果默認的Realms不能滿足你的需求,你也可以定製自己的Realms

項目集成Shiro

導入POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot-shiro-project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-shiro-project</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>


    <dependencies>
    	<!--thymeleaf整合Shiro-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
		<!--整合lombok,讓代碼變得更簡潔-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>

        <!--整合MySQl和mybatis-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!--整合數據庫連接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.19</version>
        </dependency>
        <!--整合log4j日誌-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        

		<!--整合Shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>


        <!--整合swagger2-->
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!---->


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.11.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
            <version>3.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

創建配置類

package com.example.springbootshiroproject.config;

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //設置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        Map<String,String> filterMap = new LinkedHashMap<>();

        //授權,沒有授權會跳轉到未授權頁面
        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/update","perms[user:update]");

//        filterMap.put("/user/add","authc");
        filterMap.put("/user/*","authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        //設置登錄的請求
        shiroFilterFactoryBean.setLoginUrl("/tologin");
        //未授權,跳轉的頁面
        shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
        return shiroFilterFactoryBean;
    }

	//核心的安全事務管理器 getdefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getdefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }

	//UserRealm,這是個自定義的認證類,繼承自AuthorizingRealm,負責用戶的認證和權限的處理
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    //整合shiro和thyemleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}
package com.example.springbootshiroproject.config;
//UserRealm,這是個自定義的認證類,繼承自AuthorizingRealm,負責用戶的認證和權限的處理
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    //授權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("執行了授權:doGetAuthorizationInfo");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        info.addStringPermission("user:add");
        //獲取當前登錄的對象
        Subject subject = SecurityUtils.getSubject();

        User currentUser = (User) subject.getPrincipal();
        info.addStringPermission(currentUser.getPerms());
        System.out.println(info);
        return info;
    }

    //認證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("執行了認證:doGetAuthenticationInfo");

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        User user = userService.queryUserByName(userToken.getUsername());
        if(user==null){
            return null;
        }

        //密碼認證   shiro  來做
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");
    }
}

控制層代碼

package com.example.springbootshiroproject.controller;

@Controller
public class HelloController {

    @GetMapping("/index")
    public String toIndex(Model model){
        model.addAttribute("msg","hello shiro");
        return "index";
    }

    @PostMapping("/user/add")
    public String add(){
        return "/user/add";
    }

    @PostMapping("/user/update")
    public String update(){
        return "/user/update";
    }

    @GetMapping("/tologin")
    public String login(){
        return "login";
    }

    @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) {
            model.addAttribute("msg","用戶名錯誤");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密碼錯誤");
            return "login";
        }
    }

    @GetMapping("/noauth")
    @ResponseBody
    public String unauthorized(){
        return "未經授權,不能訪問此頁面";
    }
}
  • 到這兒,與Shiro相關的代碼已經結束了。所以代碼不在列出。完成代碼請查看github自行下載,代碼都是自己寫的,也都親自跑過,可放心使用。
  • github:https://github.com/carroll1118/Shiro-Spring-Security.git

你知道的越多,你不知道的越多。
有道無術,術尚可求,有術無道,止於術。
如有其它問題,歡迎大家留言,我們一起討論,一起學習,一起進步

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章