Springboot与Shiro的整合
2021-02-11 11:18
YPE html>
标签:htm 自动 div 访问 method 依赖 known realm void
https://www.jianshu.com/p/d0b354cc5147
Springboot使用的页面模板是thyme leaf,它比jsp多一些特定的标签,可以动态或者静态显示文本内容
1、spring boot中导入thymeleaf页面模板
(1) 在pom.xml文件引入thymeleaf
org.springframework.boot spring-boot-starter-thymeleaf
(2)在application.properties(application.yml)文件中配置thymeleaf
thymeleaf:
cache: false # 关闭页面缓存
encoding: UTF-8 # 模板编码
prefix: classpath:/templates/ # 页面映射路径
suffix: .html # 试图后的后缀
mode: HTML5 # 模板模式
(3)测试导入的thymeleaf页面
/**
* 测试thymeleaf
*/
@RequestMapping("/testThymeleaf")
public String testThymeleaf(Model model){
//把数据存入model
model.addAttribute("name","qmh");
//model.addAttribute默认返回的.html文件,所以这里return的是test.html
return "/test";
}
取测试页面的name名字,建立test.html页面(注意:spring boot建立html的地方为src/main/java/resources/temelates中)
测试thymeleaf的使用
2.Springboot与Shiro整合实现用户认证
2.1shiro核心ApI
* subject(包括用户登录,注销、授权的方法,需要关联securityManager)
* securityManager:安全管理器(需要连接realm)
* realm:shiro连接数据的桥梁
2.2.Springboot与Shiro整合
(1)导入shiro与spring的依赖
org.apache.shiro shiro-spring1.4.0
(2)自定义realm类,realm类用来编写认证或授权的方式方法或者逻辑,完成shiro与其他应用的数据连接
realm类需要继承AuthorizingRealm ,实现doGetAuthorizationInfo(授权)、doGetAuthenticationInfo(认证)的方法
package com.toxic.anepoch.boot2.controller.web.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;
/**
* Title:
* Description:自定义realm类,实现shiro框架中realm部分的逻辑操作,
* (1)与securitymanager部分的关联
* (2)完成shiro与数据库的连接
*
* @author py
* @date 2020/4/16 20:07.
*
*/
public class UserRealm extends AuthorizingRealm {
//执行授权逻辑
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权认证");
return null;
}
//执行认证逻辑
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行逻辑认证");
return null;
}
}
(2)编写shiro的配置类ShiroConfigTest
创建三个对象ShiroFilterFactoryBean、DefaultSecurityManager、realm
package com.toxic.anepoch.boot2.controller.web.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;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Title:
* @author py
* @date 2020/4/16 19:42.
*/
//@Configuration 注解,表示声明该类为Spring 的配置类
@Configuration
public class ShiroConfigTest {
// 创建三个对象
/**
* 创建ShiroFilterFactoryBean(关联manager)
*/
//@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager ){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
return shiroFilterFactoryBean;
}
/**
*创建DefaultSecurityManager(关联realm对象)
*/
//@Bean
//@qualifier,qualifier的意思是合格者,通过这个标示,表明了哪个实现类才是我们所需要的,该注解是用来消除依赖注入冲突的
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}
/**
*创建realm(自定义一个realm实体类,通过实体类进行调用)
*/
//创建一个方法,方法返回对象即我们要创建的对象 UserRealm ,返回该对象的实例。在方法上打上注解@Bean即表示声明该方法返回的实例是受 Spring 管理的 Bean,便于其他方法使用
@Bean
public UserRealm getUserBealm(){
UserRealm userRealm = new UserRealm();
return userRealm;
}
}
2.3Shiro常用的内置过滤器实现url页面的拦截
* 常用的一些过滤器等级:
* anon:无需认证(登录)就可以访问
* authc:必须认证才可以访问
* user:如果使用rememberMe的功能,可以直接访问
* perms;该资源必须授予资源权限才可以访问
* role;该资源必须授予角色权限才可以访问
package com.toxic.anepoch.boot2.controller.web.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;
import java.util.LinkedHashMap;
import java.util.Map;
//@Configuration 注解,表示声明该类为Spring 的配置类
@Configuration
public class ShiroConfigTest {
/**
* 创建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager ){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器等级
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加shiro的内置过滤器,实现url的相关的拦截
/**
* 常用的一些过滤器等级:
* anon:无需认证(登录)就可以访问
* authc:必须认证才可以访问
* user:如果使用rememberMe的功能,可以直接访问
* perms;该资源必须授予资源权限才可以访问
* role;该资源必须得到角色权限才可以访问
*/
//创建一个map集合,用来参访需要拦截的url路径(controller中 @RequestMapping("/"))即及改路径的过滤等级,这里创建LinkedHashMap集合,是为了存入的数据具有顺序
Map filterMap = new LinkedHashMap();
//若拦截生效后默认跳转到login.jsp
filterMap.put("/add","authc");
filterMap.put("/update","authc");
/*
要想对user下所有的url都过滤,那么可以用* (*通配符)
filterMap.put("/user/*","authc");
*/
/*
*想对某一个url做放行处理可以用以下方法
* filterMap.put("/testThymeleaf","anon");
* */
//修改拦截的时侯跳转的页面(这里用的authc等级,就可以理解为要先完成登录),登录页面都从controller层进行关联,toLogin是controller的方法,用来访问login登录页面
shiroFilterFactoryBean.setLoginUrl("/toLogin");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
/**
*创建DefaultSecurityManager(关联realm对象)
*/
@Bean(value = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}
/**
*创建realm(自定义一个realm实体类,通过实体类进行调用)
*/
//在创建一个方法,方法返回对象即我们要创建的对象 UserRealm , 返回该对象的实例。在方法上打上注解@Bean即表示声明该方法返回的实例是受 Spring 管理的 Bean,便于其他方法使用
@Bean(value = "userRealm")
public UserRealm getUserBealm(){
UserRealm userRealm = new UserRealm();
return userRealm;
}
}
2.4Shiro用户登录操作
创建一个登陆页面:
用户的登录页面 登录
controller的登录逻辑:
//登陆的逻辑处理,接受表单中的name,password两个参数 @RequestMapping("/login") public String login(String name,String password,Model model){ //使用shiro编写认证操作 //1.获取subject对象 Subject subject = SecurityUtils.getSubject(); //2.封装用户的数据,将表单中的数据传递给token对象 UsernamePasswordToken token = new UsernamePasswordToken(name,password); //3.执行登录方法,这里使用try...catch来判断是否登录成功,若没有异常则登陆成功,有异常在进行判断并抛出异常 try { subject.login(token); System.out.println("登陆成功"); //登陆成功跳转到主页test.html (redirect:重定向) return "redirect:/hello/testThymeleaf"; } catch (UnknownAccountException e) { //用户名不存在,信息返回到html页面 model.addAttribute("msg","用户名不存在"); //返回到登陆页面 return "login"; } catch (IncorrectCredentialsException e) { //密码错误,信息返回到html页面 model.addAttribute("msg","密码错误"); //返回到登陆页面 return "login"; }
package com.toxic.anepoch.boot2.controller.web.Shiro; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; /** * Title: * Description:自定义realm类,实现shiro框架中realm部分的逻辑操作, * (1)与securitymanager部分的关联 * (2)完成shiro与数据库的连接 * * @author py * @date 2020/4/16 20:07. * */ public class UserRealm extends AuthorizingRealm { //执行授权逻辑 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行授权认证"); return null; } //执行认证逻辑 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken ) throws AuthenticationException { System.out.println("执行逻辑认证"); //假设数据库的用户名和密码分别是:qiu,123456 String name="qiu"; String password="123456"; //编写shiro的判断逻辑,判断用户名和密码是否正确 //authenticationToken类型强制转换成controller层中的UsernamePasswordToken类型,用来存放name和password // (controller中token的作用是:封装用户的数据,将表单中的数据传递给token对象,具体操作:UsernamePasswordToken token = new UsernamePasswordToken(name,password);) UsernamePasswordToken Token = (UsernamePasswordToken) authenticationToken; if(!Token.getUsername().equals(name)){ System.out.println("用户名不存在"); return null;//shiro的底层会抛出UnknownAccountException异常 }else{ //判断密码,直接创建AuthorizationInfo对象的子对象,传入password参数就可以判断密码是否一致 return new SimpleAuthenticationInfo("",password,""); } } }
2.5整合myBatis实现用户的登录
2.5.1导入myBatis的相关的依赖
com.baomidou mybatisplus-spring-boot-starter${mybatisplus-spring-boot-starter.version} com.baomidou mybatis-plus${mybatisplus.version} io.shardingjdbc sharding-jdbc-spring-boot-starter${sharding-sphere.version} mysql mysql-connector-java${mysql-connector-java.version} runtime com.alibaba druid${com.alibaba.druid.version}
2.5.2创建application.properties或application.yml文件,用来设置一些参数
//数据库的配置 datasource: type: com.alibaba.druid.pool.DruidDataSource #druid相关配置 driver-class-name: com.mysql.cj.jdbc.Driver #基本属性 url: jdbc:mysql: username: password: //mybatis的配置 mybatis: mapper-locations: classpath:mybatis/mapper/*.xml type-aliases-package: com.toxic.anepoch.boot2.service.bean
2.5.3在com.toxic.anepoch.boot2.service.bean包下创建user实体类
package com.toxic.anepoch.boot2.service.bean; /** * Title: * Description: * * @author py * @date 2020/4/19 22:15. */ public class User { private int id; private String name; private String password; public User() { } public User(int id, String name, String password) { this.id = id; this.name = name; this.password = password; } public int getId() { return id; } public void setId(int 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; } @Override public String toString() { return "User{" + "id=" + id + ", name=‘" + name + ‘\‘‘ + ", password=‘" + password + ‘\‘‘ + ‘}‘; }
2.5.4创建mapper接口实现与数据库的关联并创建mapper.xml文件
package com.toxic.anepoch.boot2.service.dao; import com.toxic.anepoch.boot2.service.bean.User; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; /** * Title:查询用户 * Description: * * @author py * @date 2020/4/19 22:22. */ @Repository //@Repository用在持久层的接口上,这个注解是将接口的一个实现类交给spring管理。 public interface UserMapper { User findByName(@Param(value = "name") String name); }
[CDATA[ id,name,password ]]>
2.5.5编写service接口和实现类,用于调用mepper接口
package com.toxic.anepoch.boot2.service.service; import com.toxic.anepoch.boot2.service.bean.User; /** * Title: * Description: * * @author py * @date 2020/4/19 22:30. */ public interface UserService { /** *通过名字进行查询 */ User findByName(String name); }
package com.toxic.anepoch.boot2.service.service.impl; import com.toxic.anepoch.boot2.service.bean.User; import com.toxic.anepoch.boot2.service.dao.UserMapper; import com.toxic.anepoch.boot2.service.service.UserService; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * Title: * Description: * * @author py * @date 2020/4/19 22:34. */ @Service public class UserServiceImpl implements UserService{ @Resource // @Resource注入mapper接口 private UserMapper userMapper; @Override public User findByName(String name) { return userMapper.findByName( name); } }
2.5.5编写Biz接口和实现类,用于调用service接口和业务的创建
package com.toxic.anepoch.boot2.biz.business; import com.toxic.anepoch.boot2.service.bean.User; /** * Title: * Description: * * @author py * @date 2020/4/19 22:58. */ public interface UserBiz { User findByName(String name); }
/** * Title: * Description: * * @author py * @date 2020/4/19 22:59. */ @Component public class UserBizImpl implements UserBiz{ @Resource private UserService userService; @Override public User findByName(String name) { return userService.findByName(name); } }
对UserRealm类进行修改
public class UserRealm extends AuthorizingRealm { //执行授权逻辑 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行授权认证"); return null; } @Autowired //@Autowired注入UserBiz接口 private UserBiz userBiz; //执行认证逻辑 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken ) throws AuthenticationException { System.out.println("执行逻辑认证"); //假设数据库的用户名和密码分别是:qiu,123456 // String name="qiu"; // String password="123456"; //编写shiro的判断逻辑,判断用户名和密码是否正确 //authenticationToken类型强制转换成controller层中的UsernamePasswordToken类型,用来存放name和password // (controller中token的作用是:封装用户的数据,将表单中的数据传递给token对象,具体操作:UsernamePasswordToken token = new UsernamePasswordToken(name,password);) UsernamePasswordToken Token = (UsernamePasswordToken) authenticationToken; User user = userBiz.findByName(Token.getUsername()); if(user==null){ System.out.println("用户名不存在"); return null;//shiro的底层会抛出UnknownAccountException异常 }else{ //判断密码,直接创建AuthorizationInfo对象的子对象,传入password参数就可以判断密码是否一致 return new SimpleAuthenticationInfo("",user.getPassword(),""); } } }
3.spring boot与shiro整合实现用户授权
3.1使用shiro的内置过滤器拦截资源
常用的授权过滤器:perms,role,授权过滤器与认证过滤器不同的是:授权过滤器需要加授权字符串,这里给add接口添加授权
//添加授权过滤器,授权字符串,授权字符串可以任意的指定 filterMap.put("/add","perms:[user:add]");
未授权过滤器生效后,会自动跳转到默认的未授权页面,当然也可以自定义一个未授权的页面
需要在controller层建立一个/noAuth路径去访问noAuth页面
//设置未授权页面,授权过滤器生效,跳转到noAuth页面 shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");
3.2编写资源授权逻辑
public class UserRealm extends AuthorizingRealm { //执行授权逻辑 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行授权认证"); //给资源授权 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //添加getShiroFilterFactoryBean方法中设置的授权字符串 info.addStringPermission("user:add"); return info; } }
3.3关联数据库实现动态授权
Springboot与Shiro的整合
标签:htm 自动 div 访问 method 依赖 known realm void
原文地址:https://www.cnblogs.com/qiumh/p/12735434.html
上一篇:p148 旋转有序数组的最小值(leetcode 153)
下一篇:Leetcode练习(Python):数组类:第54题:给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
文章标题:Springboot与Shiro的整合
文章链接:http://soscw.com/index.php/essay/54003.html