SpringBoot与Shiro整合-权限管理实战

场景

SpringBoot与Shiro整合-权限管理实战。

实现

搭建SpringBoot运行环境

打开Eclipse,new Maven Project--Create a simple project

SpringBoot与Shiro整合-权限管理实战_第1张图片

输入项目相关信息,Packing 选择为jar,点击Finish。

SpringBoot与Shiro整合-权限管理实战_第2张图片

修改项目的编译环境为1.8

打开项目的pom.xml

 
  
   
   1.8
  

添加之后--右击项目-Maven-update Project

SpringBoot与Shiro整合-权限管理实战_第3张图片

添加父级依赖

打开pom.xml


   org.springframework.boot
   spring-boot-starter-parent
   1.5.4.RELEASE
  

添加项目依赖

打开pom.xml

 
    
   
 
     org.springframework.boot
     spring-boot-starter-web
 
  

完整pom.xml


  4.0.0
 
  
   org.springframework.boot
   spring-boot-starter-parent
   1.5.4.RELEASE
  
  com.badao.springboot
  springboot-shiro
  0.0.1-SNAPSHOT
 
  
    
   
 
     org.springframework.boot
     spring-boot-starter-web
 
  
  
  
   
   1.8
  

测试SpringBoot搭建效果

在src/main/java下新建UserController

SpringBoot与Shiro整合-权限管理实战_第4张图片

代码:

package com.badao.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {

 /***
  * usercontroller测试
  */
 @RequestMapping("/hello")
 @ResponseBody
 public String hello() {
  System.out.println("**********************hello");
  return "hello";
 }


}

新建项目启动类Application.java,要与UserController同级

package com.badao;

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

/**
 * springboot启动类
 * @author badao
 * @Description:
 * @Time:2019年5月19日 下午4:20:07
 */
@SpringBootApplication
public class Application {
 public static void main(String[] args) {
  SpringApplication.run(Application.class,args);
 }
}

运行启动类

SpringBoot与Shiro整合-权限管理实战_第5张图片

启动效果

SpringBoot与Shiro整合-权限管理实战_第6张图片

打开浏览器访问

http://localhost:8080/hello

SpringBoot与Shiro整合-权限管理实战_第7张图片

 

引进Thymeleaf模板

打开pom.xml


 
 
     org.springframework.boot
     spring-boot-starter-thymeleaf   
 

在src/main/resources下新建templates目录,目录下新建test.html

SpringBoot与Shiro整合-权限管理实战_第8张图片

代码:





Thymeleaf 使用



注意:

在thymeleaf3.0以前对页面标签语法要求比较严格开始标签必须有结束标签。

所以这里手动加上结束标签。

或者这里升级thymeleaf为3.0或更高。

具体参照:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/90344773

在UserController中新建测试方法

/***
  * Thymeleaf测试
  */
 @RequestMapping("/testThymeleaf")
 public String testThymeleaf(Model model) {
  model.addAttribute("username","badao");
  return "test";
 }

运行效果

启动启动类,打开浏览器输入:

http://localhost:8080/testThymeleaf

SpringBoot与Shiro整合-权限管理实战_第9张图片

 

Shiro认证-ShiroConfig配置类

自定义Realm

新建包shiro,包下新建UserRealm.java

package com.badao.shiro;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/***
 * 自定义Realm
 * @author Administrator
 * @Description:
 * @Time:2019年5月19日 下午6:34:50
 */
public class UserRealm extends AuthorizingRealm{

 /***
  * 执行授权逻辑
  */
 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  // TODO Auto-generated method stub
  System.out.println("执行授权逻辑");
  return null;
 }

 /***
  * 执行认证逻辑
  */
 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  // TODO Auto-generated method stub
  System.out.println("执行认证逻辑");
  return null;
 }

}

ShiroConfig配置类

shiro包下新建ShiroConfig.java配置类

package com.badao.shiro;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/***
 * Shiro配置类
 * @author Administrator
 * @Description:
 * @Time:2019年5月19日 下午6:33:48
 */
@Configuration
public class ShiroConfig {
 
 /***
  * 创建ShiroFilterFactoryBean
  * @return
  */

@Bean
 public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
  ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  //设置安全管理器
  shiroFilterFactoryBean.setSecurityManager(securityManager);
  return shiroFilterFactoryBean;
 }
 
 /***
  * 创建DefaultWebSecurityManager
  * @return
  */
 @Bean(name="securityManager")
 public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm) {
  DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
  //关联realm
  securityManager.setRealm(userRealm);
  return securityManager;
 }
 /***
  * 创建Realm
  * @return
  */
 @Bean(name="userRealm")
 public UserRealm getRealm() {
  return new UserRealm(); 
 }

}

注:

通过@Bean(name="userRealm")实现添加到spring容器,然后通过@Qualifier("userRealm")去引用。

使用Shiro过滤器实现认证资源拦截

打开test.html,添加两个超链接。





Thymeleaf 使用




添加 更新

注:

进行页面的跳转时不能直接跳转到具体的页面,必须经过controller跳转。

templates下新建user目录,目录下新建add.html

 



添加用户


开始添加用户

再新建update.html





编辑用户


开始编辑用户

来到UserController中,添加跳转页面方法。

/***
  * 跳转到add
  */
 @RequestMapping("/add")
 public String add() { 
  return "user/add";
 }


 /***
  * 跳转到update
  */
 @RequestMapping("/update")
 public String update() { 
  return "user/update";
 }

运行项目,打开浏览器输入:

http://localhost:8080/testThymeleaf

SpringBoot与Shiro整合-权限管理实战_第10张图片

 

开始添加权限认证

需求:

访问首页即testThymeleaf时不进行验证,访问添加和编辑时进行拦截跳转到登录页面。

template下新建login.html





登录页面


请登录

打开ShiroConfig配置文件

添加Shiro内置过滤器:

1.anon:无需认证可以访问。

2.authc:必须认证才可以 访问。

3.user:如果使用rememberMe的功能可以直接访问。

4.perms:该资源必须得到资源权限才可以访问。

5.role:该资源必须得到角色权限才可以访问。

在getShiroFilterFactoryBean中:

@Bean
 public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
  ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  
  //设置安全管理器
  shiroFilterFactoryBean.setSecurityManager(securityManager);
  //添加Shiro内置过滤器  
  Map filterMap = new LinkedHashMap();
  filterMap.put("/add", "authc");
  filterMap.put("/update", "authc");
  //上面两行可以用通配符来配置
  //filterMap.put("/*", "authc");
  //不拦截首页
  filterMap.put("/testThymeleaf", "anon");
  shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
  //修改调整的登录页面
  shiroFilterFactoryBean.setLoginUrl("/login");
  return shiroFilterFactoryBean;
 }

在UserController中添加登录跳转

/***
  * 跳转到login
  */
 @RequestMapping("/login")
 public String login() { 
  return "login";
 }

启动项目,输入:

http://localhost:8080/testThymeleaf

效果

SpringBoot与Shiro整合-权限管理实战_第11张图片

实现用户认证(登录)操作

编写login.html





登录页面


请登录

 用户名:
 密码:
 

UserController中添加登录方法

/***
  * login
  */
 @RequestMapping("/dologin")
 public String dologin(String name,String password,Model model) { 
  
  /***
   * 使用Shiro编写认证操作
   *
   */
  //1.获取Subject
  Subject subject = SecurityUtils.getSubject();
  
  //2.封装用户数据
  UsernamePasswordToken token = new UsernamePasswordToken(name,password);
  
  //3.执行登录方法
  try {
   //登录成功,没有异常代表登录成功
   //login方法会来到UserRealm中的执行认证的方法
   subject.login(token);
   return "redirect:/testThymeleaf";
  }catch (UnknownAccountException e) {
   //登录失败:用户名不存在
   model.addAttribute("msg","用户名不存在");
   return "/login";
  }catch (IncorrectCredentialsException e){
   //登录失败:密码不正确
   model.addAttribute("msg","密码不正确");
   return "/login";
  }
  
  
 }

注:

1.subject.login(token)会自动找到自定义Realm中的执行认证的方法。

2.没有异常就是登录成功,出现UnknownAccountException 就是用户名不正确,出现IncorrectCredentialsException 就是密码不正确。

修改UserRealm

/***
  * 执行认证逻辑
  */
 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken args) throws AuthenticationException {
  // TODO Auto-generated method stub
  System.out.println("执行认证逻辑");
  //假设数据库用户名和密码
  String name = "badao";
  String password = "123";
  
  //1.判断用户名
  UsernamePasswordToken token = (UsernamePasswordToken) args;
  if(!token.getUsername().equals(name)){
   //用户名不存在
   //shiro底层会抛出UnknownAccountException
   return null;
  }
  //2.判断密码
  //编写shiro判断逻辑
  return new SimpleAuthenticationInfo("",password,"");
 }

在配置文件中给登录放行

Map filterMap = new LinkedHashMap();
  filterMap.put("/add", "authc");
  filterMap.put("/update", "authc");
  //上面两行可以用通配符来配置
  //filterMap.put("/*", "authc");
  //不拦截首页
  filterMap.put("/testThymeleaf", "anon");
  filterMap.put("/dologin", "anon");

运行项目,打开浏览器输入:

http://localhost:8080/testThymeleaf

效果

SpringBoot与Shiro整合-权限管理实战_第12张图片

 

整合MyBatis实现用户登录

导入MyBatis相关的依赖

打开pom.xml


 
 
     com.alibaba
     druid
     1.0.9
 
 
 
     mysql
     mysql-connector-java
     8.0.11
 
 
 
     org.mybatis.spring.boot
     mybatis-spring-boot-starter
     1.1.1
 

数据库中新建表

新建表Users

SpringBoot与Shiro整合-权限管理实战_第13张图片

配置application.properties

在src/main/resources下新建application.properties

SpringBoot与Shiro整合-权限管理实战_第14张图片

名字与位置必须一致。

代码:

spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shirotest?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123
#配置数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#配置别名
mybatis.type-aliases-package=com.badao.entity

新建entiry

新建entity包,包下新建User.java

package com.badao.entity;

public class User {
 
 int id;
 String userName;
 String password;

 public int getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 public String getUsername() {
  return userName;
 }
 public void setUsername(String username) {
  this.userName = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 
}

编写mapper

新建mapper包,包下新建UserMapper接口

package com.badao.mapper;

import com.badao.entity.User;

public interface UserMapper {

 public User findByName(String name);
}

再在此包新新建UserMapper.xml





编写service

新建service包,包下新建UserService接口

package com.badao.service;

import com.badao.entity.User;

public interface UserService {
 public User findByName(String name);
}

再在此包下新建UserServiceImpl

package com.badao.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.badao.entity.User;
import com.badao.mapper.UserMapper;

@Service
public class UserServiceImpl implements UserService {
 @Autowired
 private UserMapper userMapper;

 @Override
 public User findByName(String name) {
  // TODO Auto-generated method stub
  return userMapper.findByName(name);
 }


}

修改Controller

打开UserController,添加如下登录方法。

/***
  * 跳转到login
  */
 @RequestMapping("/login")
 public String login() { 
  return "login";
 }
 
 /***
  * login
  */
 @RequestMapping("/dologin")
 public String dologin(String name,String password,Model model) { 
  
  /***
   * 使用Shiro编写认证操作
   *
   */
  //1.获取Subject
  Subject subject = SecurityUtils.getSubject();
  
  //2.封装用户数据
  UsernamePasswordToken token = new UsernamePasswordToken(name,password);
  
  //3.执行登录方法
  try {
   //登录成功,没有异常代表登录成功
   //login方法会来到UserRealm中的执行认证的方法
   subject.login(token);
   return "redirect:/testThymeleaf";
  }catch (UnknownAccountException e) {
   //登录失败:用户名不存在
   model.addAttribute("msg","用户名不存在");
   return "/login";
  }catch (IncorrectCredentialsException e){
   //登录失败:密码不正确
   model.addAttribute("msg","密码不正确");
   return "/login";
  }
  
  
 }

修改Realm

打开UserRealm.java,修改为:

/***
  * 执行认证逻辑
  */
 @Override
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken args) throws AuthenticationException {
  // TODO Auto-generated method stub
  System.out.println("执行认证逻辑");
  //假设数据库用户名和密码
  /*String name = "badao";
  String password = "123";*/
  UsernamePasswordToken token = (UsernamePasswordToken) args;
  User user = userService.findByName(token.getUsername());
  //1.判断用户名
  
  if(user==null){
   //用户名不存在
   //shiro底层会抛出UnknownAccountException
   return null;
  }
  //2.判断密码
  //编写shiro判断逻辑
  return new SimpleAuthenticationInfo("",user.getPassword(),"");
 }

修改ShiroConfig

打开ShiroConfig,放开登录页面

Map filterMap = new LinkedHashMap();
  filterMap.put("/add", "authc");
  filterMap.put("/update", "authc");
  //上面两行可以用通配符来配置
  //filterMap.put("/*", "authc");
  //不拦截首页
  filterMap.put("/testThymeleaf", "anon");
  filterMap.put("/login", "anon");
  shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

修改login.html


请登录

 用户名:
 密码:
 

修改启动类

打开Application.java,添加@MapperScan("com.badao.mapper"):

@SpringBootApplication
@MapperScan("com.badao.mapper")
public class Application {
 public static void main(String[] args) {
  SpringApplication.run(Application.class,args);
 }
}

整合MyBatis后项目结构

SpringBoot与Shiro整合-权限管理实战_第15张图片

整合MyBatis后效果

SpringBoot与Shiro整合-权限管理实战_第16张图片

使用Shiro过滤器实现授权页面拦截

修改配置文件

打开ShiroConfig配置文件,添加授权过滤器。

//授权过滤器
  //注意:当授权拦截后,shiro会自动跳转到未授权页面
  filterMap.put("/add", "perms[user:add]");

设置未授权提示页面

shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");

打开UserController,添加未授权页面跳转

/***
  * 跳转到未授权页面
  */
 @RequestMapping("/login")
 public String login() { 
  return "login";
 }

在templates下新建unAuth.html





没有授权


没有授权

运行效果

SpringBoot与Shiro整合-权限管理实战_第17张图片

编写资源授权逻辑

修改UserRealm

/***
  * 执行授权逻辑
  */
 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  // TODO Auto-generated method stub
  System.out.println("执行授权逻辑");
  
  //给资源进行授权
  SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
  
  //添加资源的授权字符串
  info.addStringPermission("user:add");
  
  return info;
 }

注意:

添加资源的授权字符串要与上面进行拦截的字符串一致才能跳过拦截。

效果:

SpringBoot与Shiro整合-权限管理实战_第18张图片

关联数据库实现动态授权

为了简单的进行测试,不再建立角色表与权限表。

改造Users表

直接添加权限列。

SpringBoot与Shiro整合-权限管理实战_第19张图片

授予badao用户 user:add权限

授予liumang用户 user:update权限

改造User.java实体类

package com.badao.entity;

public class User {
 
 int id;
 String userName;
 String password;
 public String getPerms() {
  return perms;
 }
 public void setPerms(String perms) {
  this.perms = perms;
 }
 String perms;

 public int getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 public String getUsername() {
  return userName;
 }
 public void setUsername(String username) {
  this.userName = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 
}

UserMapper.xml中添加方法

UserMapper接口中添加方法

public User findById(int id);

UserService中添加方法

public User findById(int id);

UserServiceImpl实现方法

@Override
 public User findById(int id) {
  // TODO Auto-generated method stub
  return userMapper.findById(id);
 }

添加更新的权限拦截

打开Shiroconfig.java

//注意:当授权拦截后,shiro会自动跳转到未授权页面
  filterMap.put("/add", "perms[user:add]");
  filterMap.put("/update", "perms[user:update]");

执行授权逻辑查询数据库修改

打开UserRealm.java

/***
  * 执行授权逻辑
  */
 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  // TODO Auto-generated method stub
  System.out.println("执行授权逻辑");
  
  //给资源进行授权
  SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
  
  //添加资源的授权字符串
  //info.addStringPermission("user:add");
  //获取当前登录用户
  Subject subject = SecurityUtils.getSubject();
  User user = (User)subject.getPrincipal();
  userService.findById(user.getId());
  info.addStringPermission(user.getPerms());
  return info;
 }

注:

User user = (User)subject.getPrincipal();这句中的getPrincipal()就是获取下面执行逻辑认证的


return new SimpleAuthenticationInfo(user,user.getPassword(),"");

第一个参数。

效果

SpringBoot与Shiro整合-权限管理实战_第20张图片

Thymeleaf整合Shiro权限标签

导入thymeleaf扩展坐标

打开pom.xml


     com.github.theborakompanioni
     thymeleaf-extras-shiro
     2.0.0
 

配置ShiroDialect

打开ShiroConfig

/***
  * 配置ShiroDialect 用于thymeleaf和Shiro便签配合使用
  */
 @Bean
 public ShiroDialect getShiroDialect() {
  return new ShiroDialect();
  
 }

页面中使用

打开test.html





Thymeleaf 使用





登录

效果

SpringBoot与Shiro整合-权限管理实战_第21张图片

 

源码下载

https://download.csdn.net/download/badao_liumang_qizhi/11194439


 

你可能感兴趣的:(SpringBoot,Shiro)