SpringBoot与Shiro整合

Posted mxj961116

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot与Shiro整合相关的知识,希望对你有一定的参考价值。

修改pom.xml

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

 

<!-- 继承Spring Boot的默认父工程 -->

<!-- Spring Boot 父工程 -->

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.5.4.RELEASE</version>

</parent>

 

<groupId>com.mxj</groupId>

<artifactId>springboot-shiro</artifactId>

<version>0.0.1-SNAPSHOT</version>

</project>

1.1. 导入web支持

修改pom.xml

<!-- 导入依赖 -->

<dependencies>

<!-- 导入web支持:SpringMVC开发支持,Servlet相关的程序 -->

<!-- web支持,SpringMVC, Servlet支持等 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

</dependencies>

1.2. 编写测试Controller

package com.mxj.controller;

 

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;

 

@Controller

public class UserController

 

/**

 * 测试方法

 */

@RequestMapping("/hello")

@ResponseBody

public String hello()

System.out.println("UserController.hello()");

return "ok";

 

1.3. 编写SpringBoot启动类

package com.mxj;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

/**

 * SpringBoot启动类

 * @author MA

 *

 */

@SpringBootApplication

public class Application 

 

public static void main(String[] args)

SpringApplication.run(Application.class, args);

 

1.4. 导入thymeleaf页面模块

引入thymeleaf依赖

 

<!-- 导入thymeleaf依赖 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-thymeleaf</artifactId>

</dependency>

 

Controller添加测试方法

 

/**

 * 测试thymeleaf

 */

@RequestMapping("/testThymeleaf")

public String testThymeleaf(Model model)

//把数据存入model

model.addAttribute("name", "mxj");

//返回test.html

return "test";

 

建立test.html页面

 

src/main/resource目录下创建templates目录,然后创建test.html页面

 

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>测试Thymeleaf的使用</title>

</head>

<body>

<h3 th:text="$name"></h3>

</body>

</html>

 

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

 

如果希望页面语法不严谨,但是也能够运行成功,可以把thymeleaf升级为3.0或以上版本。

 

升级thymeleaf3.0.2版本:

<!-- 修改参数 -->

<properties>

<!-- 修改JDK的编译版本为1.8 -->

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

<!-- 修改thymeleaf的版本 -->

<thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>

<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>

</properties>

2. Spring BootShiro整合实现用户认证

2.1. 分析Shiro的核心API

Subject: 用户主体(把操作交给SecurityManager

SecurityManager:安全管理器(关联Realm

RealmShiro连接数据的桥梁

2.2. Spring Boot整合Shiro

2.2.1. 导入shirospring整合依赖

修改pom.xml

<!-- shiro与spring整合依赖 -->

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-spring</artifactId>

<version>1.4.0</version>

</dependency>

 

2.2.2. 自定义Realm

package com.mxj.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 MA

 *

 */

public class UserRealm extends AuthorizingRealm

 

/**

 * 执行授权逻辑

 */

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)

System.out.println("执行授权逻辑");

return null;

 

/**

 * 执行认证逻辑

 */

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException

System.out.println("执行认证逻辑");

return null;

 

 

 

2.2.3. 编写Shiro配置类(*

package com.mxj.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 MA

 *

 */

@Configuration

public class ShiroConfig 

 

/**

 * 创建ShiroFilterFactoryBean

 */

    @Bean

public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager)

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

 

//设置安全管理器

shiroFilterFactoryBean.setSecurityManager(securityManager);

 

return shiroFilterFactoryBean;

 

/**

 * 创建DefaultWebSecurityManager

 */

@Bean(name="securityManager")

public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm)

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

//关联realm

securityManager.setRealm(userRealm);

return securityManager;

 

/**

 * 创建Realm

 */

@Bean(name="userRealm")

public UserRealm getRealm()

return new UserRealm();

 

 

2.3. 使用Shiro内置过滤器实现页面拦截

package com.mxj.shiro;

 

import java.util.LinkedHashMap;

import java.util.Map;

 

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 MA

 *

 */

@Configuration

public class ShiroConfig

 

/**

 * 创建ShiroFilterFactoryBean

 */

@Bean

public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager)

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

 

//设置安全管理器

shiroFilterFactoryBean.setSecurityManager(securityManager);

 

//添加Shiro内置过滤器

/**

 * Shiro内置过滤器,可以实现权限相关的拦截器

 *    常用的过滤器:

 *       anon: 无需认证(登录)可以访问

 *       authc: 必须认证才可以访问

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

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

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

 */

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

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

filterMap.put("/update", "authc");*/

 

filterMap.put("/testThymeleaf", "anon");

 

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

 

//修改调整的登录页面

shiroFilterFactoryBean.setLoginUrl("/toLogin");

 

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

 

 

return shiroFilterFactoryBean;

 

/**

 * 创建DefaultWebSecurityManager

 */

@Bean(name="securityManager")

public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm)

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

//关联realm

securityManager.setRealm(userRealm);

return securityManager;

 

/**

 * 创建Realm

 */

@Bean(name="userRealm")

public UserRealm getRealm()

return new UserRealm();

 

 

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

2.4.1. 设计登录页面

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>登录页面</title>

</head>

<body>

<h3>登录</h3>

<form method="post" action="login">

用户名:<input type="text" name="name"/><br/>

密码:<input type="password" name="password"/><br/>

<input type="submit" value="登录"/>

</form>

</body>

</html>

 

2.4.2. 编写Controller的登录逻辑

 

/**

 * 登录逻辑处理

 */

@RequestMapping("/login")

public String login(String name,String password,Model model)

 

/**

 * 使用Shiro编写认证操作

 */

//1.获取Subject

Subject subject = SecurityUtils.getSubject();

 

//2.封装用户数据

UsernamePasswordToken token = new UsernamePasswordToken(name,password);

 

//3.执行登录方法

try 

subject.login(token);

 

//登录成功

//跳转到test.html

return "redirect:/testThymeleaf";

catch (UnknownAccountException e)

//e.printStackTrace();

//登录失败:用户名不存在

model.addAttribute("msg", "用户名不存在");

return "login";

catch (IncorrectCredentialsException e)

//e.printStackTrace();

//登录失败:密码错误

model.addAttribute("msg", "密码错误");

return "login";

 

2.4.3. 编写Realm的判断逻辑

package com.mxj.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.authc.UsernamePasswordToken;

import org.apache.shiro.authz.AuthorizationInfo;

import org.apache.shiro.realm.AuthorizingRealm;

import org.apache.shiro.subject.PrincipalCollection;

 

/**

 * 自定义Realm

 * @author MA

 *

 */

public class UserRealm extends AuthorizingRealm

 

/**

 * 执行授权逻辑

 */

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)

System.out.println("执行授权逻辑");

return null;

 

/**

 * 执行认证逻辑

 */

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException

System.out.println("执行认证逻辑");

 

//假设数据库的用户名和密码

String name = "eric";

String password = "123456";

 

//编写shiro判断逻辑,判断用户名和密码

//1.判断用户名

UsernamePasswordToken token = (UsernamePasswordToken)arg0;

if(!token.getUsername().equals(name))

//用户名不存在

return null;//shiro底层会抛出UnKnowAccountException

 

//2.判断密码

return new SimpleAuthenticationInfo("",password,"");

 

 

 

2.5. 整合MyBatis实现登录

2.5.1. 导入mybatis相关的依赖

<!-- 导入mybatis相关的依赖 -->

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

<version>1.0.9</version>

</dependency>

<!-- mysql -->

<dependency>

<groupId>mysql</groupId>

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

</dependency>

<!-- SpringBoot的Mybatis启动器 -->

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>1.1.1</version>

</dependency>

 

2.5.2. 配置application.properties

位置:src/main/resources目录下

 

spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/ssm

spring.datasource.username=root

spring.datasource.password=123456

 

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

 

mybatis.type-aliases-package=com.mxj.dao

 

2.5.3. 编写User实体

package com.mxj.dao;

 

public class User

private Integer id;

private String name;

private String password;

public Integer getId()

return id;

public void setId(Integer id)

this.id = id;

public String getName()

return name;

public void setName(String name)

this.name = name;

public String getPassword()

return password;

public void setPassword(String password)

this.password = password;

 

 

 

2.5.4. 编写UserMapper接口

package com.mxj.mapper;

 

import com.itheima.domain.User;

 

public interface UserMapper

 

public User findByName(String name);

 

 

2.5.5. 编写UserMapper.xml映射文件

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE mapper

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 该文件存放CRUD的sql语句 -->

<mapper namespace="com.itheima.mapper.UserMapper">

 

<select id="findByName" parameterType="string" resultType="user">

SELECT id,

NAME,

PASSWORD

FROM

user where name = #value

</select>

</mapper>

2.5.6. 编写业务接口和实现

接口:

package com.mxj.service;

 

import com.itheima.domain.User;

 

public interface UserService

 

public User findByName(String name);

 

 

实现;

package com.mxj.service.impl;

 

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

import org.springframework.stereotype.Service;

 

import com.itheima.domain.User;

import com.itheima.mapper.UserMapper;

import com.itheima.service.UserService;

 

@Service

public class UserServiceImpl implements UserService

 

//注入Mapper接口

@Autowired

private UserMapper userMapper;

 

@Override

public User findByName(String name)

return userMapper.findByName(name);

 

 

 

 

2.5.7. 添加@MapperScan注解

package com.mxj;

 

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

/**

 * SpringBoot启动类

 * @author MA

 *

 */

@SpringBootApplication

@MapperScan("com.mxj.mapper")

public class Application

 

public static void main(String[] args)

SpringApplication.run(Application.class, args);

 

 

2.5.8. 修改UserRealm

package com.mxj.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.authc.UsernamePasswordToken;

import org.apache.shiro.authz.AuthorizationInfo;

import org.apache.shiro.realm.AuthorizingRealm;

import org.apache.shiro.subject.PrincipalCollection;

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

 

import com.mxj.dao.User;

import com.mxj.service.UserService;

 

/**

 * 自定义Realm

 * @author MA

 *

 */

public class UserRealm extends AuthorizingRealm

 

/**

 * 执行授权逻辑

 */

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)

System.out.println("执行授权逻辑");

return null;

 

@Autowired

private UserService userSerivce;

 

/**

 * 执行认证逻辑

 */

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException

System.out.println("执行认证逻辑");

 

//编写shiro判断逻辑,判断用户名和密码

//1.判断用户名

UsernamePasswordToken token = (UsernamePasswordToken)arg0;

 

User user = userSerivce.findByName(token.getUsername());

 

if(user==null)

//用户名不存在

return null;//shiro底层会抛出UnKnowAccountException

 

//2.判断密码

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

 

 

3. Spring BootShiro整合实现用户授权

3.1. 使用Shiro内置过滤器拦截资源

/**

 * 创建ShiroFilterFactoryBean

 */

@Bean

public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager)

ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

 

//设置安全管理器

shiroFilterFactoryBean.setSecurityManager(securityManager);

 

//添加Shiro内置过滤器

/**

 * Shiro内置过滤器,可以实现权限相关的拦截器

 *    常用的过滤器:

 *       anon: 无需认证(登录)可以访问

 *       authc: 必须认证才可以访问

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

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

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

 */

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

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

filterMap.put("/update", "authc");*/

 

filterMap.put("/testThymeleaf", "anon");

//放行login.html页面

filterMap.put("/login", "anon");

 

//授权过滤器

//注意:当前授权拦截后,shiro会自动跳转到未授权页面

filterMap.put("/add", "perms[user:add]");

 

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

 

//修改调整的登录页面

shiroFilterFactoryBean.setLoginUrl("/toLogin");

//设置未授权提示页面

shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");

 

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

 

 

return shiroFilterFactoryBean;

3.2. 完成Shiro的资源授权

UserRealm

/**
* 执行授权逻辑
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)

System.out.println("执行授权逻辑");
//给资源进行授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

//添加资源的授权字符串
//info.addStringPermission("user:add");

//到数据库查询当前用户的授权字符串
//获取当前登陆用户
Subject subject = SecurityUtils.getSubject();
String name= (String) subject.getPrincipal();
User user = userService.findByName(name);

info.addStringPermission(user.getPerms());
return info;

 

4.  thymeleafshiro标签整合使用

4.1. 导入thymeleaf扩展坐标

<!-- thymelshiro的扩展坐标 -->

<dependency>

<groupId>com.github.theborakompanioni</groupId>

<artifactId>thymeleaf-extras-shiro</artifactId>

<version>2.0.0</version>

</dependency>

4.2. 配置ShiroDialect

ShiroConfig类里面添加getShiroDialect方法

/**

 * 配置ShiroDialect,用于thymeleafshiro标签配合使用

 */

@Bean

public ShiroDialect getShiroDialect()

return new ShiroDialect();

4.3. 在页面上使用shiro标签

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>测试Thymeleaf的使用</title>

</head>

<body>

<h3 th:text="$name"></h3>

 

<hr/>

<div shiro:hasPermission="user:add">

进入用户添加功能: <a href="add">用户添加</a><br/>

</div>

<div shiro:hasPermission="user:update">

进入用户更新功能: <a href="update">用户更新</a><br/>

</div>

<a href="toLogin">登录</a>

</body>

</html>

以上是关于SpringBoot与Shiro整合的主要内容,如果未能解决你的问题,请参考以下文章

Springboot与Shiro的整合

SpringBoot与Shiro整合

Session管理 --《springboot与shiro整合》

springboot整合shiro的认证与授权流程

SpringBoot整合Shiro 一:搭建环境

springboot整合shiro(完整版)