1分钟学会SpringBoot2知识点,让你35岁不再失业(六)

1分钟学会SpringBoot2知识点,让你35岁不再失业(六)

第二十四节、springboot 权限管理框架shiro

1、shiro简介
shiro是apache的一个开源框架,而且呢是一个权限管理的框架,用于实现用户认证、用户授权。spring 中也有一个权限框架 spring
security (原名Acegi),它和 spring 依赖过于紧密,没有 shiro 使用简单。shiro 不依赖于 spring,shiro 不仅可以实现 web应用的权限
管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。使用shiro实现系统的权限
管理,有效提高开发效率,从而降低开发成本。
2、shrio基本框架

在这里插入图片描述
在这里插入图片描述
3、认证流程
在这里插入图片描述

  1. 构建SecurityManager环境
  2. 主体提交认证
  3. SecurityManager 处理
  4. 流转到 Authenticator 执行认证
  5. 通过 Realm 获取相关的用户信息(获取验证数据进行验证)
    4、授权流程
    在这里插入图片描述
  6. 创建构建SecurityManager环境
  7. 主体提交授权认证
  8. SecurityManager 处理
  9. 流转到 Authorizor 授权器执行授权认证
  10. 通过 Realm 从数据库或配置文件获取角色权限数据返回给授权器,进行授权。
    4、shiro项目构建
    pom.xml
<?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.8.BUILD-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.unionpay.springboot</groupId>
    <artifactId>shiro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>shiro</name>
    <description>Demo project for Spring Boot</description>

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

    <dependencies>


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

        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.21</version>
        </dependency>


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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </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>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </pluginRepository>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

</project>


创建ShiroApplicationTests 类

package com.unionpay.springboot.shiro;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.realm.SimpleAccountRealm;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class ShiroApplicationTests {



/*
用户认证
1. 构建SecurityManager环境
2. 主体提交认证
3. SecurityManager 处理
4. 流转到 Authenticator 执行认证
5. 通过 Realm 获取相关的用户信息(获取验证数据进行验证)
 */

    @Test
    public void authentication() {
        //1、 构建一个安全管理器环境
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();

        SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
        simpleAccountRealm.addAccount("yyliu", "123456");
        defaultWebSecurityManager.setRealm(simpleAccountRealm);
        SecurityUtils.setSecurityManager(defaultWebSecurityManager);
        //2、主体提交认证
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("yyliu", "1234567");

        //3. SecurityManager 处理
        try {
            subject.login(usernamePasswordToken);
            System.out.println("用户认证的状态:" + subject.isAuthenticated());
            subject.logout();//退出
            System.out.println("用户认证的状态:" + subject.isAuthenticated());

        } catch (UnknownAccountException uae) {
            System.out.println("用户不存在");
        } catch (IncorrectCredentialsException ice) {
            System.out.println("用户密码不匹配");
        } catch (LockedAccountException lae) {
            System.out.println("账号已被锁定");

        } catch (AuthenticationException ae) {
            System.out.println("用户认证异常");
        }

    }

    /*用户授权
    1. 构建SecurityManager环境
    2. 主体提交授权认证
    3. SecurityManager 处理
    4. 流转到 Authorizor 授权器执行授权认证
    5. 通过 Realm 从数据库或配置文件获取角色权限数据返回给授权器,进行授权。
 */

    @Test
    public void authorization() {
        //1. 构建SecurityManager环
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
        simpleAccountRealm.addAccount("zhangsan", "666666","admin","test");
        defaultWebSecurityManager.setRealm(simpleAccountRealm);
        SecurityUtils.setSecurityManager(defaultWebSecurityManager);

        //2、 主体提交授权认证
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("zhangsan", "666666");

        //3. SecurityManager 处理
        try {
            subject.login(usernamePasswordToken);
            System.out.println("用户授权的状态:" + subject.isAuthenticated());
           // subject.checkRoles("admin","test");
            subject.checkRoles("test");
            subject.logout();
            System.out.println("用户授权的状态:" + subject.isAuthenticated());
            //if no exception, that's it, we're done!
        } catch (UnknownAccountException uae) {
            System.out.println("用户不存在");
        } catch (IncorrectCredentialsException ice) {
            System.out.println("用户密码不匹配");
        } catch (LockedAccountException lae) {
            System.out.println("账号已被锁定");

        } catch (AuthenticationException ae) {
            System.out.println("用户认证异常");
        }catch (UnauthorizedException e){
            System.out.println("该用户没有权限访问");
        }
    }

    //通过配置文件的方式去读取保存的权限
    @Test
    public void testIniRealm(){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        //classpath为自己建的文件
        IniRealm iniRealm=new IniRealm("classpath:shiro.ini");
        defaultWebSecurityManager.setRealm(iniRealm);
        SecurityUtils.setSecurityManager(defaultWebSecurityManager);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("admin", "123456");

        try {
            subject.login(usernamePasswordToken);
            System.out.println("用户认证的状态" + subject.isAuthenticated());
            subject.checkRoles("admin");
            subject.checkPermissions("user:deleted","role:list");
            subject.logout();
            System.out.println("用户认证的状态" + subject.isAuthenticated());
            //if no exception, that's it, we're done!
        } catch (UnknownAccountException uae) {
            System.out.println("用户不存在");
        } catch (IncorrectCredentialsException ice) {
            System.out.println("用户密码不匹配");
        } catch (LockedAccountException lae) {
            System.out.println("账号已被锁定");

        } catch (AuthenticationException ae) {
            System.out.println("用户认证异常");
        }catch (UnauthorizedException e){
            System.out.println("该用户没有权限访问");
        }
    }

    /**
     * 通过mysql的方式保存权限
     */

    @Test
    public void testJdbcRealm(){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        JdbcRealm jdbcRealm=new JdbcRealm();
        //jdbc数据源添加
        DruidDataSource druidDataSource=new DruidDataSource();
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/shiro?useSSL=false");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("6415772");
        druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        jdbcRealm.setPermissionsLookupEnabled(true);
        String authenticationQuery = "select password from users where username = ?";
        String userRolesQuery = "select role_name from user_roles where username = ?";
        String permissionsQuery = "select permission from roles_permissions where role_name = ?";
        jdbcRealm.setAuthenticationQuery(authenticationQuery);
        jdbcRealm.setUserRolesQuery(userRolesQuery);
        jdbcRealm.setPermissionsQuery(permissionsQuery);
        jdbcRealm.setDataSource(druidDataSource);
        defaultWebSecurityManager.setRealm(jdbcRealm);
        SecurityUtils.setSecurityManager(defaultWebSecurityManager);
        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("test", "123456");

        try {
            subject.login(usernamePasswordToken);
            System.out.println("用户认证的状态" + subject.isAuthenticated());
            subject.checkRoles("test");
            subject.checkPermissions("user:deleted","user:list");
            subject.logout();
            System.out.println("用户认证的状态" + subject.isAuthenticated());
            //if no exception, that's it, we're done!
        } catch (UnknownAccountException uae) {
            System.out.println("用户不存在");
        } catch (IncorrectCredentialsException ice) {
            System.out.println("用户密码不匹配");
        } catch (LockedAccountException lae) {
            System.out.println("账号已被锁定");

        } catch (AuthenticationException ae) {
            System.out.println("用户认证异常");
        }catch (UnauthorizedException e){
            System.out.println("该用户没有权限访问");
        }

    }


    /**
     * 自定义Realm进行认证授权
     */

    @Test
    public void testCustomRealm(){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        CustomRealm customRealm=new CustomRealm();
        defaultWebSecurityManager.setRealm(customRealm);
        SecurityUtils.setSecurityManager(defaultWebSecurityManager);
        Subject subject = SecurityUtils.getSubject();


        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("admin", "123456");

        try {
            subject.login(usernamePasswordToken);
            System.out.println("用户认证的状态" + subject.isAuthenticated());
            subject.checkRoles("test");
            subject.checkPermissions("user:deleted","user:list","role:list");
            subject.logout();
            System.out.println("用户认证的状态" + subject.isAuthenticated());
            //if no exception, that's it, we're done!
        } catch (UnknownAccountException uae) {
            System.out.println("用户不存在");
        } catch (IncorrectCredentialsException ice) {
            System.out.println("用户密码不匹配");
        } catch (LockedAccountException lae) {
            System.out.println("账号已被锁定");

        } catch (AuthenticationException ae) {
            System.out.println("用户认证异常");
        }catch (UnauthorizedException e){
            System.out.println("该用户没有权限访问");
        }
    }

/**
 * 不加盐加密详细认证
 */

@Test
public void testMatcher(){
    DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
    CustomRealm customRealm=new CustomRealm();
    HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
    matcher.setHashAlgorithmName("md5");
    matcher.setHashIterations(3);
    customRealm.setCredentialsMatcher(matcher);
    defaultWebSecurityManager.setRealm(customRealm);
    SecurityUtils.setSecurityManager(defaultWebSecurityManager);
    Subject subject = SecurityUtils.getSubject();


    UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("admin", "123456");

    try {
        subject.login(usernamePasswordToken);
        System.out.println("用户认证的状态" + subject.isAuthenticated());
        subject.checkRoles("test");
        subject.checkPermissions("user:deleted","user:list","role:list");
        subject.logout();
        System.out.println("用户认证的状态" + subject.isAuthenticated());
        //if no exception, that's it, we're done!
    } catch (UnknownAccountException uae) {
        System.out.println("用户不存在");
    } catch (IncorrectCredentialsException ice) {
        System.out.println("用户密码不匹配");
    } catch (LockedAccountException lae) {
        System.out.println("账号已被锁定");

    } catch (AuthenticationException ae) {
        System.out.println("用户认证异常");
    }catch (UnauthorizedException e){
        System.out.println("该用户没有权限访问");
    }
}


    /**
     * 加盐加密详细认证
     */


    @Test
    public void testSaltMatcher(){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        CustomRealm customRealm=new CustomRealm();
        HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");

        //这里的次数要匹配
        matcher.setHashIterations(3);
        customRealm.setCredentialsMatcher(matcher);
        defaultWebSecurityManager.setRealm(customRealm);
        SecurityUtils.setSecurityManager(defaultWebSecurityManager);
        Subject subject = SecurityUtils.getSubject();


        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("admin", "123456");

        try {
            subject.login(usernamePasswordToken);
            System.out.println("用户认证的状态" + subject.isAuthenticated());
            subject.checkRoles("test");
            subject.checkPermissions("user:deleted","user:list","role:list");
            subject.logout();
            System.out.println("用户认证的状态" + subject.isAuthenticated());
            //if no exception, that's it, we're done!
        } catch (UnknownAccountException uae) {
            System.out.println("用户不存在");
        } catch (IncorrectCredentialsException ice) {
            System.out.println("用户密码不匹配");
        } catch (LockedAccountException lae) {
            System.out.println("账号已被锁定");

        } catch (AuthenticationException ae) {
            System.out.println("用户认证异常");
        }catch (UnauthorizedException e){
            System.out.println("该用户没有权限访问");
        }
    }
}


创建CustomRealm类

package com.unionpay.springboot.shiro;

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.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 刘阳洋
 * @date 2020/5/20 20:13
 */
public class CustomRealm extends AuthorizingRealm {

    /**
     * mock 用户信息
     * @param principalCollection
     * @return
     */
    private Map<String,String> userMap=new HashMap<>();
    {
        userMap.put("admin","123456");
        userMap.put("test","123456");
    }
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        String username= (String) principalCollection.getPrimaryPrincipal();
        List<String> roles=getRolesByUserName(username);
        List<String> permissions=getPermissionsByUsername(username);
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addRoles(roles);
        info.addStringPermissions(permissions);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String) authenticationToken.getPrincipal();
        String password=getPasswordByUsername(username);
        if(StringUtils.isEmpty(password)){
            return null;
        }
//        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(username,password,getName());
//        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(username,getEncPassword(password),getName());
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(username,getEncPassword(password,username),getName());
        info.setCredentialsSalt(ByteSource.Util.bytes(username));
        return info;

    }

//    private String getEncPassword(String password){
//        return new Md5Hash(password,null,3).toString();
//    }

    private String getEncPassword(String password,String salt){
        return new Md5Hash(password,salt,3).toString();
    }
    /**
     * 通过用户名获取密码
     * @Author:      刘阳洋
     * @UpdateUser:
     * @Version:     0.0.1
     * @param username
     * @return       java.lang.String
     * @throws
     */
    private String getPasswordByUsername(String username){

        return userMap.get(username);
    }




    /**
     * 通过用户名获取用户拥有角色信息
     * @Author:
     * @UpdateUser:
     * @Version:     0.0.1
     * @param username
     * @return       java.util.List<java.lang.String>
     * @throws
     */
    private List<String> getRolesByUserName(String username){

        List<String> roles=new ArrayList<>();
        if(username.equals("admin")){
            roles.add("admin");
        }
        roles.add("test");
        return roles;
    }
    /**
     * 通过用户名获取用户拥有权限信息
     * @Author:
     * @UpdateUser:
     * @Version:     0.0.1
     * @param username
     * @return       java.util.List<java.lang.String>
     * @throws
     */
    private List<String> getPermissionsByUsername(String username){

        List<String> permissions=new ArrayList<>();
        if(username.equals("admin")){
            permissions.add("*");
        }
        permissions.add("user:list");
        permissions.add("user:deleted");
        permissions.add("user:edit");
        return permissions;
    }

}

创建sql语句

CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(25) DEFAULT NULL,
`password` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



CREATE TABLE `user_roles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_name` varchar(25) DEFAULT NULL,
`username` varchar(25) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



CREATE TABLE `roles_permissions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`permission` varchar(255) DEFAULT NULL,
`role_name` varchar(25) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


  INSERT INTO `shiro`.`users` (`id`, `username`, `password`) VALUES ('1', 'admin', '123456');
  INSERT INTO `shiro`.`users` (`id`, `username`, `password`) VALUES ('2', 'test', '123456');
  INSERT INTO `shiro`.`user_roles` (`id`, `role_name`, `username`) VALUES ('1', 'admin', 'admin');
  INSERT INTO `shiro`.`user_roles` (`id`, `role_name`, `username`) VALUES ('2', 'test', 'test');
  INSERT INTO `shiro`.`roles_permissions` (`id`, `permission`, `role_name`) VALUES ('1',
  'user:deleted', 'test');
  INSERT INTO `shiro`.`roles_permissions` (`id`, `permission`, `role_name`) VALUES ('2',
  'user:list', 'test');
  INSERT INTO `shiro`.`roles_permissions` (`id`, `permission`, `role_name`) VALUES ('3', '*',
  'admin');
  INSERT INTO `shiro`.`roles_permissions` (`id`, `permission`, `role_name`) VALUES ('4',
  'user:edit', 'test');

创建shiro.ini

[users]
test=123456,test
admin=123456,admin

[roles]
test=user:list,user:edit
admin=*

启动类

package com.unionpay.springboot.shiro;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ShiroApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShiroApplication.class, args);
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值