天天看点

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

前言:

学习的地址:https://www.majiaxueyuan.com/front/showcoulist 、https://www.bilibili.com/video/av44084437

SpringBoot的pom依赖(以2.0版本为例的)

本集记录的是shiro的权限框架(记录的是一个比较偏向实战的demo)

使用了springboot + freemark + shiro+mybatis 这样的框架

注意:有些代码是在上一章 https://blog.csdn.net/qq_28198181/article/details/97929008 上的

demo层次:

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试
学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

大体流程:

从页面得到登录密码和用户,进入数据库查询,如果有就能进入主页,如果不能,就返回登录页面。登录到主页之后,根据用户的角色显示不同的权限进行不同的操作。

这里面还需要处理realm的授权操作。就是对用户的权限进行判断。

目录

1.添加依赖

2.配置application.properties文件

3.创建数据库表和和字段

4.创建实体类和mapper接口

5.修改realm的认证和授权方法

6.修改前端显示方法。

7.测试

1.添加依赖

在上次之前的demo依赖上还需要添加前端支持shiro的依赖和连接数据库的依赖,所有的依赖如下:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
    </parent>

    <dependencies>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 引入freeMarker的依赖包. -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

        <!-- shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>

        <!-- 前端支持shiro的标签-->
        <dependency>
            <groupId>net.mingsoft</groupId>
            <artifactId>shiro-freemarker-tags</artifactId>
            <version>0.1</version>
        </dependency>


        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>

        <!-- atomikos 用于处理多数数据源配置的事务管理 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>

   <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
        </dependency>

    </dependencies>


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

暂时使用到的依赖就这么多。

2.配置application.properties文件

application.properties在上一次的基础上还需要添加连接数据库的配置

server.port=8080
server.tomcat.uri-encoding=UTF-8
spring.freemarker.allow-request-override=false
spring.freemarker.cache=true
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.expose-spring-macro-helpers=false
spring.freemarker.suffix=.ftl
spring.freemarker.template-loader-path=classpath:/templates/
mysql.datasource.data.borrowConnectionTimeout=30
mysql.datasource.data.loginTimeout=30
mysql.datasource.data.maintenanceInterval=60
mysql.datasource.data.maxIdleTime=60
mysql.datasource.data.maxLifetime=20000
mysql.datasource.data.maxPoolSize=25
mysql.datasource.data.minPoolSize=3
mysql.datasource.data.password=jy897513;
mysql.datasource.data.url=jdbc:mysql://localhost:3306/bootdb2?useUnicode=true&characterEncoding=utf-8
mysql.datasource.data.username=root
           

自己根据自己数据库去配置连接地址

暂时使用的如上。

3.创建数据库表和和字段

数据库中涉及到的表如下:

1.用户表user

用户表是记录登录的用户名称和密码,简单点就只是创建了三个字段 uid uname 和 upassword

CREATE TABLE user(
uid INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
uname VARCHAR(20) NOT NULL,
upassword VARCHAR(20) NOT NULL
);
           

2.角色表role

角色表是判断用户的在当前系统中是什么角色,是普通user用户还是admin管理用户

也只是设置3个字段 rid rname 和 rdescription 

CREATE TABLE role(
rid INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
rname VARCHAR(20),
rdescription VARCHAR(100)
);
           

3.权限表permission

权限表只是自己加的,用来判断什么角色拥有什么权限,根据权限来显示可执行的操作

权限也只是写了三个参数 pid pname pdescription

CREATE TABLE permission(
pid INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
pname VARCHAR(20),
pdescription VARCHAR(100)
);
           

4.用户表和角色表的关联表

记录用户id和角色id的关联表 可以根据用户id查询到角色 

也只是设置了三个字段 urid uid 和rid

CREATE TABLE role_user(
urid INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
uid INT NOT NULL,
rid INT NOT NULL
);
           

目的就是为了得到用户后可以去知道他是什么角色 为后面得到权限做准备

5.角色表和权限表的关联表  

设置了三个字段 rpid rid 和pid

CREATE TABLE role_permission(
rpid INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
rid INT NOT NULL,
pid INT NOT NULL
);
           

这样的所以用到的数据库表就创建好了

4.创建实体类和mapper接口

实体类创建是为了能从数据库中取得数据组成PO,

具体有三个实体类,分别就是role user 和permission 

user:

@Data
public class User {

    private Integer uid;

    private String uname;

    private String upassword;
}
           

role:

@Data
public class Role {

    private Integer rid;

    private String rname;

    private String rdescription;

}
           

permission:

@Data
public class Permission {

    private Integer pid;

    private String pname;

    private String pdescription;

}
           

实体类创建好后需要配置数据源(我就直接用多数据源配置了)

dbconfig类:

@Data
@ConfigurationProperties(prefix = "mysql.datasource.data")
public class DBConfig {

    private String url;
    private String username;
    private String password;
    private int minPoolSize;
    private int maxPoolSize;
    private int maxLifetime;
    private int borrowConnectionTimeout;
    private int loginTimeout;
    private int maintenanceInterval;
    private int maxIdleTime;
    private String testQuery;
}
           

扫描配置文件前缀为 mysql.datasource.data开头的参数。

mybatisConfigure类

@Configuration
@MapperScan(basePackages = "com.zqj.mapper",sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class MyBatisPrimaryConfig {

	@Bean(name = "primaryDataSource")
	@Primary
	public DataSource primaryDataSource(DBConfig dbConfig) throws SQLException {
		//配置数据库参数
		MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
		mysqlXaDataSource.setUrl(dbConfig.getUrl());
		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
		mysqlXaDataSource.setPassword(dbConfig.getPassword());
		mysqlXaDataSource.setUser(dbConfig.getUsername());
		AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();

		xaDataSource.setXaDataSource(mysqlXaDataSource);
		xaDataSource.setUniqueResourceName("primaryDataSource");

		xaDataSource.setMinPoolSize(dbConfig.getMinPoolSize());
		xaDataSource.setMaxPoolSize(dbConfig.getMaxPoolSize());
		xaDataSource.setMaxLifetime(dbConfig.getMaxLifetime());
		xaDataSource.setBorrowConnectionTimeout(dbConfig.getBorrowConnectionTimeout());
		xaDataSource.setLoginTimeout(dbConfig.getLoginTimeout());
		xaDataSource.setMaintenanceInterval(dbConfig.getMaintenanceInterval());
		xaDataSource.setMaxIdleTime(dbConfig.getMaxIdleTime());
		xaDataSource.setTestQuery(dbConfig.getTestQuery());
		return xaDataSource;
	}

    @Primary
	@Bean(name = "pariamrySqlSessionFactory")
	public SqlSessionFactory testSqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource)
			throws Exception {
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		return bean.getObject();
	}

    @Primary
	@Bean(name = "primarySqlSessionTemplate")
	public SqlSessionTemplate testSqlSessionTemplate(
			@Qualifier("pariamrySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
		return new SqlSessionTemplate(sqlSessionFactory);
	}
}
           

配置的datasource扫描的mapper包在com.zqj.mapper

这个时候就是需要去编写mapper接口了

创建mapper包 然后我创建了三个mapper

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

usermapper 用来查询用户的

@Mapper
@Repository
public interface UserMapper {

    @Select("SELECT * FROM user WHERE uname LIKE #{username} limit 1;")
    public User getUser(@Param("username") String username);

}
           

RoleUserMapper

是用来根据用户查询对应绑定的角色

@Mapper
@Repository
public interface RoleUserMapper {

    @Select("SELECT r.rid, r.rname,r.rdescription FROM user u,role r,role_user ru WHERE u.uname =#{userName} and u.uid = ru.uid and ru.rid = r.rid;")
    List<Role> getRoleList(@Param("userName") String userName);

}
           

RolePermissionMapper

是根据用户角色来查询绑定的权限的

@Mapper
@Repository
public interface RolePermissionMapper {


    @Select("SELECT p.pid,p.pname FROM permission p , role_permission pr ,role r WHERE r.rname = #{roleName} and r.rid =pr.rid and p.pid=pr.pid;")
    List<Permission> getPermissions(@Param("roleName") String roleName);
}
           

mapper写好后,就可以连接数据库了

5.修改realm的认证和授权方法

mapper 是实体都创建好了,可以去修改realm的认证和授权了。

现将以前写死的认证方法的password改了:

@Autowired
private UserMapper userMapper;

  @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        String username = (String) authenticationToken.getPrincipal(); //传递过来的username 就是登陆的用户名称

//        String dbpassWord = "123"; //这里模拟的是数据库的用户密码
        User user = userMapper.getUser(username);

        System.out.println("进入认证Realm:" + user.toString());

        //这里是处理某处登陆后,当前登录失效的方法,就像异地登录那样
        Collection<Session> sessions = sessionDAO.getActiveSessions();
        for (Session session : sessions) {
            String loginedUserName = String.valueOf(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY));
            if (username.equals(loginedUserName)) {
                //说明已经是登陆成功的了。需要挤掉
                session.setTimeout(0L);
                break;
            }
        }

        SimpleAuthenticationInfo simpleAuthorizationInfo = null;

        //这里是将username 和 数据库得到的密码放进去 最后一个参数可以写死
        //实战是在数据库查到数据后将这个数据放进去
        //后期还可以加盐
        simpleAuthorizationInfo = new SimpleAuthenticationInfo(username, user.getUpassword(), "realName");
        return simpleAuthorizationInfo;
    }
           

认证修改后,如果用户正常登录的话,就可以去处理授权的问题了。

处理授权是需要首先在前端获得shiro传递过来的参数:

前台shiro tags和后台的联动:这个是处理shiro的标签

@Component
public class FreemarkShiroConfig {

    @Autowired
    private FreeMarkerConfigurer configurer;

    //设置shrio和freemark联动的标签
    @PostConstruct
    public void setShiroTags() {
        configurer.getConfiguration().setSharedVariable("shiro",new ShiroTags());
    }
}
           

当前后台联动处理好了后就会根据shiro进入到authorizationInfo的doGetAuthrizationInfo方法

授权主要是在登陆之后进行用户角色判断和权限判断:将得到的用户名查询到对应的角色和权限

@Autowired
private RolePermissionMapper rolePermissionMapper;

 /**
     * 授权
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //得到当前用户名称
        String username = (String) principalCollection.getPrimaryPrincipal();

        
        System.out.println("进入到授权Realm:" + username);

        //得到从数据库取出的用户的角色对象列表和全县列表
        List<Role> dbRoleList = roleUserMapper.getRoleList(username);
        List<Permission> dbPermissionList = new ArrayList<>();

        //要添加的角色列表
        List<String> roleList = new ArrayList<>();

        //要添加的权限列表
        List<String> permissionList = new LinkedList<>();
        //得到数据库的角色列表

        for (Role role : dbRoleList) {
            //添加角色名称
            roleList.add(role.getRname());
            //权限列表
            //得到角色拥有的权限
            dbPermissionList = rolePermissionMapper.getPermissions(role.getRname());
             for (Permission permission : dbPermissionList) {
                if (permission.getPname().equals("SELECT")) {
                    permissionList.add("ADMIN:USER:"+permission.getPname());
                }else{
                    permissionList.add(role.getRname()+":"+permission.getPname());
                }
            }
        }

        //把角色列表和权限列表发送过来
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
         //这里是将得到的角色列表和权限列表放到授权对象中
        simpleAuthorizationInfo.addRoles(roleList);
        simpleAuthorizationInfo.addStringPermissions(permissionList);
        return simpleAuthorizationInfo;
    }
           

接下来可以去处理前端显示了

6.修改前端显示方法

将授权写好后,可以将其体现到前端去

index页面是显示得到的角色信息和权限信息

index页面使用shiro标签时会找到联动的@requiresRole 和 @RequiresPermission

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<head >
    <meta charset="UTF-8"/>
    <title></title>
</head>
<body>
你好啊:${name}
</br>
</br>
你当前的角色是:
<@shiro.hasRole name="ADMIN"> <!--对应的是 @requiresRole -->
<p>ADMIN角色</p>
</@shiro.hasRole>

<@shiro.hasRole name="USER">
<p>USER角色</p>
</@shiro.hasRole>

<@shiro.hasRole name="MANAGER">
<p>MANAGER角色</p>
</@shiro.hasRole>

你当前可以操作的功能有:
<@shiro.hasPermission name="ADMIN:UPDATE"><!--对应的是 @requiresPermission -->
<p>UPDATE功能</p>
</@shiro.hasPermission>

<@shiro.hasPermission name="ADMIN:DELETE">
<p>DELETE功能</p>
</@shiro.hasPermission>

<@shiro.hasPermission name="ADMIN:INSERT">
<p>INSERT功能</p>
</@shiro.hasPermission>

<@shiro.hasPermission name="ADMIN:USER:SELECT">
<p>SELECT功能</p>
</@shiro.hasPermission>

退出:
<form action="toLogout" method="get">
    <input type="submit" name="logout" value="退出"/><br/>
</form>

</body>
</html>
           

上面的@shiro.xxxxx的就是要去userRealm的授权中查找得到的角色数据和权限数据

name后面跟的是 用户角色:权限  这样的表达方式

现在数据库中还没有 等下写进去

最后将dbconfig.class进行在程序执行的时候去加载:

@SpringBootApplication
@EnableConfigurationProperties({DBConfig.class})
public class ShiroApplication {

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

}
           

7.测试

大体流程写完了,现在在数据库中放些数据

用户表:

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

角色表:

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

权限表:

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

用户角色关联表:

表示的是我姬子阿姐有管理员权限和普通用户权限

神舟平板只有普通用户权限

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

然后将权限表和角色关联表关联起来:

ADMIN用户拥有增删改查所有功能

USER用户拥有查询功能

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

后台数据库也模拟好了,

http://localhost:8080/index/getIndex
           

这个时候可以操作一波试试了

访问indexContrller

访问index界面

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

会跳转回到login界面 ,因为没有认证通过的

接着

我们来输入用户密码 随便输一个,会报错输入错误

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

现在我们输入一个正确的数据来尝试一下

学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试
学习的spring boot 2.0的记录(十一):SpringBoot关于Shiro的配置(基于mybatis的实战的demo)1.添加依赖2.配置application.properties文件3.创建数据库表和和字段4.创建实体类和mapper接口5.修改realm的认证和授权方法6.修改前端显示方法7.测试

以上。

没有很严谨的去写。可能有些规范不好。请指正