Shiro整合SpringBoot项目实战

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。
个人主页:Java Fans的博客
个人信条:不迁怒,不贰过。小知识,大智慧。
当前专栏:SpringBoot 框架从入门到精通
✨特色专栏:国学周更-心性养成之路
本文内容:Shiro整合SpringBoot项目实战

文章目录

      • 6.0 整合思路
      • 6.1 创建springboot项目
      • 6.2 引入shiro依赖
      • 6.3 配置shiro环境
          • 0.创建配置类
          • 1.配置shiroFilterFactoryBean
          • 2.配置WebSecurityManager
          • 3.创建和配置自定义realm
          • 4.编写主页面index.jsp
          • 5.启动项目,访问index.jsp
          • 6.加入权限控制
          • 7.重启项目访问查看
      • 6.4 常见过滤器
      • 6.5 认证实现
          • 1. 在login.jsp中开发认证界面
          • 2. 开发controller
          • 3.开发realm中返回静态数据(未连接数据库)
          • 4.启动项目以realm中定义静态数据进行认证
      • 6.6 退出认证
          • 1.开发页面退出连接
          • 2.开发controller
          • 3.修改退出连接访问退出路径
          • 4.退出之后访问受限资源立即返回认证界面
      • 6.7 MD5、Salt的认证实现
        • 1.开发数据库注册
          • 0.开发注册界面
          • 1.创建数据表结构
          • 2.项目引入依赖
          • 3.配置application.properties配置文件
          • 4.创建entity
          • 5.创建DAO接口
          • 6.开发mapper配置文件
          • 7.开发service接口
          • 8.创建salt工具类
          • 9.开发service实现类
          • 10.开发Controller
          • 11.启动项目进行注册
        • 2.开发数据库认证
          • 0.开发DAO
          • 1.开发mapper配置文件
          • 2.开发Service接口
          • 3.开发Service实现类
          • 4.开发在工厂中获取bean对象的工具类
          • 5.修改自定义realm
          • 6.修改ShiroConfig中realm

在这里插入图片描述

6.0 整合思路

Shiro整合SpringBoot项目实战_第1张图片

6.1 创建springboot项目

Shiro整合SpringBoot项目实战_第2张图片

6.2 引入shiro依赖

在pom.xml文件中添加Shiro依赖。可以选择使用Shiro的starter,也可以手动添加Shiro的依赖。

<dependency>
  <groupId>org.apache.shirogroupId>
  <artifactId>shiro-spring-boot-starterartifactId>
  <version>1.5.3version>
dependency>

6.3 配置shiro环境

0.创建配置类

在Spring Boot应用程序中,可以通过编写一个Shiro配置类来配置Shiro。在该类中,可以定义Shiro的安全管理器Realm过滤器等组件,并将它们注入Spring容器中。

Shiro整合SpringBoot项目实战_第3张图片

1.配置shiroFilterFactoryBean

Shiro过滤器是实现基于角色或权限的访问控制的核心组件。可以通过编写一个ShiroFilter配置类来定义Shiro过滤器链,并将其注入到Spring容器中。

@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){
  //创建shiro的filter
  ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
  //注入安全管理器
  shiroFilterFactoryBean.setSecurityManager(securityManager);
 	
  return shiroFilterFactoryBean;
}
2.配置WebSecurityManager

DefaultWebSecurityManager类主要定义了设置subjectDao,获取会话模式,设置会话模式,设置会话管理器,是否是http会话模式等操作,它继承了DefaultSecurityManager类,实现了WebSecurityManager接口

@Bean
public DefaultWebSecurityManager getSecurityManager(Realm realm){
  DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
  defaultWebSecurityManager.setRealm(realm);
  return defaultWebSecurityManager;
}
3.创建和配置自定义realm

在Shiro中,Realm是连接应用程序和安全数据源的桥梁。通过实现自定义的Realm,可以将Shiro连接到应用程序的数据库、LDAP目录或其他数据源中。在自定义Realm中,需要实现认证授权逻辑,并将其注入到Shiro的安全管理器中。

在这里插入图片描述

public class CustomerRealm extends AuthorizingRealm {
    //处理授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
		//处理认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 
      																																		
        return null;
    }
}
//创建自定义realm
@Bean
public Realm getRealm(){
  return new CustomerRealm();
}
4.编写主页面index.jsp

Shiro整合SpringBoot项目实战_第4张图片

5.启动项目,访问index.jsp

Shiro整合SpringBoot项目实战_第5张图片

默认在配置好shiro环境后默认环境中没有对项目中任何资源进行权限控制,所有现在项目中所有资源都可以通过路径访问

6.加入权限控制

修改ShiroFilterFactoryBean配置

public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        //配置系统的受限资源   authc
        //配置系统的公共资源   anon
        HashMap<String, String> map = new HashMap<>();
        map.put("/index.jsp", "authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        shiroFilterFactoryBean.setLoginUrl("/login.jsp");
        return  shiroFilterFactoryBean;

 }

/** 代表拦截项目中一切资源 authc 代表shiro中的一个filter的别名,详细内容看文档的shirofilter列表

7.重启项目访问查看

Shiro整合SpringBoot项目实战_第6张图片

6.4 常见过滤器

  • 注意: shiro提供和多个默认的过滤器,我们可以用这些过滤器来配置控制指定url的权限:
配置缩写 对应的过滤器 功能
anon AnonymousFilter 指定url可以匿名访问
authc FormAuthenticationFilter 指定url需要form表单登录,默认会从请求中获取usernamepassword,rememberMe等参数并尝试登录,如果登录不了就会跳转到loginUrl配置的路径。我们也可以用这个过滤器做默认的登录逻辑,但是一般都是我们自己在控制器写登录逻辑的,自己写的话出错返回的信息都可以定制嘛。
authcBasic BasicHttpAuthenticationFilter 指定url需要basic登录
logout LogoutFilter 登出过滤器,配置指定url就可以实现退出功能,非常方便
noSessionCreation NoSessionCreationFilter 禁止创建会话
perms PermissionsAuthorizationFilter 需要指定权限才能访问
port PortFilter 需要指定端口才能访问
rest HttpMethodPermissionFilter 将http请求方法转化成相应的动词来构造一个权限字符串,这个感觉意义不大,有兴趣自己看源码的注释
roles RolesAuthorizationFilter 需要指定角色才能访问
ssl SslFilter 需要https请求才能访问
user UserFilter 需要已登录“记住我”的用户才能访问

6.5 认证实现

1. 在login.jsp中开发认证界面

Shiro整合SpringBoot项目实战_第7张图片

<form action="${pageContext.request.contextPath}/user/login" method="post">
  用户名:<input type="text" name="username" > <br/>
  密码  : <input type="text" name="password"> <br>
  <input type="submit" value="登录">
form>
2. 开发controller
@Controller
@RequestMapping("user")
public class UserController {
  /**
    * 用来处理身份认证
    * @param username
    * @param password
    * @return
    */
  @RequestMapping("login")
  public String login(String username,String password){
    //获取主体对象
    Subject subject = SecurityUtils.getSubject();
    try {
      subject.login(new UsernamePasswordToken(username,password));
      return  "redirect:/index.jsp";
    } catch (UnknownAccountException e) {
      e.printStackTrace();
      System.out.println("用户名错误!");
    }catch (IncorrectCredentialsException e){
      e.printStackTrace();
      System.out.println("密码错误!");
    }
    return "redirect:/login.jsp";
  }
}
  • 在认证过程中使用subject.login进行认证
3.开发realm中返回静态数据(未连接数据库)
@Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("==========================");
        String principal = (String) token.getPrincipal();
        if("mosin".equals(principal)){
            return new SimpleAuthenticationInfo(principal,"123",this.getName());
        }
        return null;
    }
}
4.启动项目以realm中定义静态数据进行认证

Shiro整合SpringBoot项目实战_第8张图片

Shiro整合SpringBoot项目实战_第9张图片

Shiro整合SpringBoot项目实战_第10张图片

  • 认证功能没有md5和随机盐的认证就实现啦

6.6 退出认证

1.开发页面退出连接

Shiro整合SpringBoot项目实战_第11张图片

2.开发controller
@Controller
@RequestMapping("user")
public class UserController {
  /**
    * 退出登录
    *
    */
  @RequestMapping("logout")
  public String logout(){
    Subject subject = SecurityUtils.getSubject();
    subject.logout();//退出用户
    return "redirect:/login.jsp";
  }
}
3.修改退出连接访问退出路径

Shiro整合SpringBoot项目实战_第12张图片

4.退出之后访问受限资源立即返回认证界面

Shiro整合SpringBoot项目实战_第13张图片

6.7 MD5、Salt的认证实现

1.开发数据库注册

0.开发注册界面
<h1>用户注册h1>
<form action="${pageContext.request.contextPath}/user/register" method="post">
  用户名:<input type="text" name="username" > <br/>
  密码  : <input type="text" name="password"> <br>
  <input type="submit" value="立即注册">
form>

Shiro整合SpringBoot项目实战_第14张图片

1.创建数据表结构
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(6) NOT NULL AUTO_INCREMENT,
  `username` varchar(40) DEFAULT NULL,
  `password` varchar(40) DEFAULT NULL,
  `salt` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;

Shiro整合SpringBoot项目实战_第15张图片

2.项目引入依赖

<dependency>
  <groupId>org.mybatis.spring.bootgroupId>
  <artifactId>mybatis-spring-boot-starterartifactId>
  <version>2.1.2version>
dependency>


<dependency>
  <groupId>mysqlgroupId>
  <artifactId>mysql-connector-javaartifactId>
  <version>5.1.38version>
dependency>



<dependency>
  <groupId>com.alibabagroupId>
  <artifactId>druidartifactId>
  <version>1.1.19version>
dependency>
3.配置application.properties配置文件
server.port=8888
server.servlet.context-path=/shiro
spring.application.name=shiro

spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp
#新增配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shiro?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root


mybatis.type-aliases-package=cn.kgc.springboot_jsp_shiro.entity
mybatis.mapper-locations=classpath:mapper/*.xml

4.创建entity
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String  id;
    private String username;
    private String password;
    private String salt;
}
5.创建DAO接口
@Mapper
public interface UserDAO {
    void save(User user);
}
6.开发mapper配置文件
<insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">
  insert into t_user values(#{id},#{username},#{password},#{salt})
insert>
7.开发service接口
public interface UserService {
    //注册用户方法
    void register(User user);
}
8.创建salt工具类
public class SaltUtils {
    /**
     * 生成salt的静态方法
     * @param n
     * @return
     */
    public static String getSalt(int n){
        char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            char aChar = chars[new Random().nextInt(chars.length)];
            sb.append(aChar);
        }
        return sb.toString();
    }
}
9.开发service实现类
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDAO userDAO;

    @Override
    public void register(User user) {
        //处理业务调用dao
        //1.生成随机盐
        String salt = SaltUtils.getSalt(8);
        //2.将随机盐保存到数据
        user.setSalt(salt);
        //3.明文密码进行md5 + salt + hash散列
        Md5Hash md5Hash = new Md5Hash(user.getPassword(),salt,1024);
        user.setPassword(md5Hash.toHex());
        userDAO.save(user);
    }
}
10.开发Controller
@Controller
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserService userService;

    /**
     * 用户注册
     */
    @RequestMapping("register")
    public String register(User user) {
        try {
            userService.register(user);
            return "redirect:/login.jsp";
        }catch (Exception e){
            e.printStackTrace();
            return "redirect:/register.jsp";
        }
    }
}
11.启动项目进行注册

在这里插入图片描述

2.开发数据库认证

0.开发DAO
@Mapper
public interface UserDAO {

    void save(User user);
		//根据身份信息认证的方法
    User findByUserName(String username);
}
1.开发mapper配置文件
<select id="findByUserName" parameterType="String" resultType="User">
  select id,username,password,salt from t_user
  where username = #{username}
select>
2.开发Service接口
public interface UserService {
    //注册用户方法
    void register(User user);
    //根据用户名查询业务的方法
    User findByUserName(String username);
}
3.开发Service实现类
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDAO userDAO;
    @Override
    public User findByUserName(String username) {
        return userDAO.findByUserName(username);
    }
}
4.开发在工厂中获取bean对象的工具类
@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }


    //根据bean名字获取工厂中指定bean 对象
    public static Object getBean(String beanName){
        return context.getBean(beanName);
    }
}
5.修改自定义realm
 @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("==========================");

        //根据身份信息
        String principal = (String) token.getPrincipal();
        //在工厂中获取service对象
        UserService userService = (UserService) ApplicationContextUtils.getBean("userService");
				//根据身份信息查询
        User user = userService.findByUserName(principal);

        if(!ObjectUtils.isEmpty(user)){
            //返回数据库信息
            return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), 
                                               ByteSource.Util.bytes(user.getSalt()),this.getName());
        }
        return null;
    }
6.修改ShiroConfig中realm

使用凭证匹配器以及hash散列

@Bean
public Realm getRealm(){
  CustomerRealm customerRealm = new CustomerRealm();
  //设置hashed凭证匹配器
  HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
  //设置md5加密
  credentialsMatcher.setHashAlgorithmName("md5");
  //设置散列次数
  credentialsMatcher.setHashIterations(1024);
  customerRealm.setCredentialsMatcher(credentialsMatcher);
  return customerRealm;
}

Shiro整合SpringBoot项目实战_第16张图片


  码文不易,本篇文章就介绍到这里,如果想要学习更多Java系列知识点击关注博主,博主带你零基础学习Java知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。

你可能感兴趣的:(SpringBoot,框架从入门到精通,spring,boot,java,spring,shiro,缓存)