SpringBoot与Shiro整合-权限管理实战视频笔记(之二)

本文内容大部分来自黑马视频的SpringBoot与Shiro整合-权限管理实战视频,在此记录为个人学习笔记。
可按步骤操作,无法实操的实战blog都是耍流氓。

    • 三、shiro认证-ShiroConfig配置类
          • 1. shiro的核心API
          • 2. Spring整合shiro
    • 四、shiro认证-使用shiro过滤器实现认证资源拦截
          • 1. 在templates下新建user/add.html和user/update.html
          • 2. 在UserController中编写访问这两个页面的方法
          • 3. 在testThymeleaf.html页面中添加这两个页面的超链接
          • 4. 在getShiroFilterFactoryBean方法中添加拦截
          • 5. 修改拦截后跳转的页面
          • 6. 试试用通配符拦截
    • 五、shiro认证-实现用户登录功能
          • 1. 修改完善之前的login.html页面
          • 2. 在UserController中编写/login请求,编写登录的处理逻辑
          • 3. 在UserRealm中编写shiro认证逻辑
          • 4. 启动程序,进行测试
    • 六、shiro认证-整合MyBatis完善用户登录
          • 1. 导入Mybatis相关的依赖
          • 2. 配置application.properties(src/main/resources下)
          • 3. 编写User实体类
          • 4. 编写接口UserMapper.java(dao)
          • 5. 编写UserMapper.xml映射文件
          • 6. 编写UserService.java业务接口
          • 7. 编写UserServiceImpl.java业务实现类
          • 8. 在启动类添加@MapperScan注解,开启Mybatis的Mapper接口扫描
          • 9. 修改UserRealm.java,调用刚编写的业务
          • 10. run

三、shiro认证-ShiroConfig配置类

1. shiro的核心API
  • Subject:用户主体(关联SecurityManager,把操作交给SecurityManager)
  • SecurityManager:安全管理器(关联Realm)
  • Realm:shiro连接数据库的桥梁
2. Spring整合shiro

(1)导入shiro和spring整合依赖


        <dependency>
            <groupId>org.apache.shirogroupId>
            <artifactId>shiro-springartifactId>
            <version>1.4.0version>
        dependency>

(2)自定义Realm类

package com.fukaiit.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;

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;
    }

}

(3)编写shiro配置类(基本结构)

package com.fukaiit.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 * */
@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 getdefaultDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        //关联Realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    /** * 创建Realm */

    @Bean(name="userRealm")
    public UserRealm getRealm(){
        return new UserRealm();
    }
}

四、shiro认证-使用shiro过滤器实现认证资源拦截

1. 在templates下新建user/add.html和user/update.htmlSpringBoot与Shiro整合-权限管理实战视频笔记(之二)_第1张图片
2. 在UserController中编写访问这两个页面的方法
@RequestMapping("/add")
    public String add() {
        return "user/add";
    }

    @RequestMapping("/update")
    public String update() {
        return "user/update";
    }
3. 在testThymeleaf.html页面中添加这两个页面的超链接
进入用户新增页面:<a href="add">用户新增a>
进入用户更新页面:<a href="update">用户更新a>

测试可访问。

4. 在getShiroFilterFactoryBean方法中添加拦截
@Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean =new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //添加shiro内置过滤器,实现权限相关的url拦截
        /** * 常见过滤器: * anon:无需认证(登录)可以访问 * authc:必须认证才可以访问 * user:如果使用Remember Me的功能,可以直接访问 * perms:该资源必须得到资源权限才可以访问 * role:该资源必须得到角色权限才可以访问 */
        Map filterMap=new LinkedHashMap();
        filterMap.put("/add", "authc");
        filterMap.put("/update", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

拦截之后重启,再次访问发现:试图访问add或者update,会自动跳转到login.jsp页面

5. 修改拦截后跳转的页面

(1)在templates下新增login.html页面
(2)在ShiroConfig中shiroFilterFactoryBean方法中修改拦截后跳转的页面

//修改跳转的登录页面
        shiroFilterFactoryBean.setLoginUrl("/toLogin");

(3)在UserController中添加toLogin方法

@RequestMapping("/toLogin")
    public String toLogin() {
        return "login";
    }

测试,当没有权限跳转到该login.html页面

6. 试试用通配符拦截
filterMap.put("/testThymeleaf", "anon");
        filterMap.put("/*", "authc");

五、shiro认证-实现用户登录功能

1. 修改完善之前的login.html页面

<html>
<head>
<meta charset="UTF-8">
<title>登录页面title>
head>
<body>
    <h1>登录页面h1>   
    <span style="color:red" th:text="${msg}">span>
    <form method="post" action="login">
        <input type="text" name="username" /><br>
        <input type="password" name="password"><br>
        <input type="submit" name="submit" value="登录">
    form> 
body>
html>
2. 在UserController中编写/login请求,编写登录的处理逻辑
@RequestMapping("/login")
    public String login(String usernam,String password,Model model) {
        /** * 使用shiro编写认证操作 */
        //获取Subject
        Subject subject=SecurityUtils.getSubject();
        //封装用户数据
        UsernamePasswordToken token=new UsernamePasswordToken(usernam,password);
        //执行登录方法
        try {
            //只要执行login方法,就会去执行UserRealm中的认证逻辑
            subject.login(token);

            //如果没有异常,代表登录成功
            //跳转到textThymeleaf页面,代表主页
            return "redirect:/testThymeleaf";
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            //登录失败
            model.addAttribute("msg","用户名不存在");
            return "login";

        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            model.addAttribute("msg","密码错误");
            return "login";
        }
    }

测试发现,并没有进入/login请求,是因为之前写的拦截器(/*)拦截了所有请求,再对/login请求放行filterMap.put("/login", "anon");
重启测试,发现执行了认证逻辑,返回了用户名不存在异常。

3. 在UserRealm中编写shiro认证逻辑
@Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
        System.out.println("执行认证逻辑");

        //先写模拟数据进行验证,下一步再连接数据库,假设数据库的用户名和密码如下
        String dbusername="fukaiit";
        String dbpassword="123456";

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

        //1. 判断用户名
        UsernamePasswordToken token=(UsernamePasswordToken) arg0;
        if (!token.getUsername().equals(dbusername)) {
            //用户名不存在
            return null;//shiro底层会抛出UnknownAccountException
        }
        //2. 判断密码
        return new SimpleAuthenticationInfo("",dbpassword,"");//参数1:需要返回给login方法的数据;参数2:数据库密码,shiro会自动判断 

    }
4. 启动程序,进行测试

SpringBoot与Shiro整合-权限管理实战视频笔记(之二)_第2张图片

六、shiro认证-整合MyBatis完善用户登录

1. 导入Mybatis相关的依赖

        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druidartifactId>
            <version>1.0.9version>
        dependency>

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

        
        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>1.1.1version>
        dependency>
2. 配置application.properties(src/main/resources下)

(1)创建用户表

-- 创建用户表
CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), PASSWORD VARCHAR(20) );

(2)配置application.properties

spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot-shiro
spring.datasource.username=root
spring.datasource.password=root

# 连接池配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

# mybatis 别名扫描
mybatis.type-aliases-package=com.fukaiit.domain
3. 编写User实体类
package com.fukaiit.domain;

public class User {
    private Integer id;
    private String username;
    private String password;

    //getter and setter methods
}
4. 编写接口UserMapper.java(dao)
package com.fukaiit.mapper;

import com.fukaiit.domain.User;

public interface UserMapper {
    public User findByUsername(String username);
}
5. 编写UserMapper.xml映射文件


<mapper namespace="com.fukaiit.mapper.UserMapper">
  <select id="findByUsername" parameterType="String" resultType="User" >
    select id,username,password from user where username = #{value}
  select>
mapper>

Tips:
1. xml的名字必须与接口文件的名字一致;
2. mapper中的namespace必须与接口类的全名一致

6. 编写UserService.java业务接口
package com.fukaiit.service;

import com.fukaiit.domain.User;

public interface UserService {
    public User findByUsername(String username);
}
7. 编写UserServiceImpl.java业务实现类
package com.fukaiit.service.impl;

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

import com.fukaiit.domain.User;
import com.fukaiit.mapper.UserMapper;
import com.fukaiit.service.UserService;

@Service
public class UserServiceImpl implements UserService{

    @Autowired
    private UserMapper userMapper;

    @Override
    public User findByUsername(String username) {
        return userMapper.findByUsername(username);
    }

}
8. 在启动类添加@MapperScan注解,开启Mybatis的Mapper接口扫描
@MapperScan("com.fukaiit.mapper")
9. 修改UserRealm.java,调用刚编写的业务
@Autowired
    private UserService userService;

    /** * 执行认证逻辑 */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
        System.out.println("执行认证逻辑");

        //编写shiro判断逻辑,判断用户名和密码
        //1. 判断用户名
        UsernamePasswordToken token=(UsernamePasswordToken) arg0;
        User user = userService.findByUsername(token.getUsername());
        if (user==null) {
            //用户名不存在
            return null;//shiro底层会抛出UnknownAccountException
        }
        //2. 判断密码
        return new SimpleAuthenticationInfo("",user.getPassword(),"");//参数1:需要返回给login方法的数据;参数2:数据库密码,shiro会自动判断 

    }
10. run

效果同上节最后。

你可能感兴趣的:(Java)