Springboot整合Shiro

目录

1.springboot整合shiro-----认证(登录)

1.1.创建springboot项目

1.2.引依赖

1.3.修改application配置文件

1.4.创建实体类

1.5.创建dao层

1.6.创建service层

1.7.编写realm

1.8.创建vo层

1.9.创建Controller层

1.10. 创建shiro的配置类

1.11.创建登录页面与登录成功页面

1.12.测试

2.springboot整合shiro--授权(权限)

2.1.修改Realm

2.2.创建Service

2.3.创建PermissionDao 

2.4.创建PermissionDao.xml

2.5.创建UserController

2.6.修改登录成功页面

2.7.添加依赖

2.8.ShiroConfig修改

测试

 2.9.权限不足时跳转到一个页面

3.springboot整合shiro----前后端分离

创建Result 

3.1.登录成功或失败---返回json数据

3.2.权限不足时---返回json数据

3.3.未登录时---返回json数据

 4.shiro权限对象缓存到redis中

5.使用Swagger2接口文档测试


1.springboot整合shiro-----认证(登录)

1.1.创建springboot项目

1.2.引依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    <!--shiro和springboot整合的依赖-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

1.3.修改application配置文件

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///shiro?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456789

#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

mybatis-plus.mapper-locations=classpath:/mapper/*.xml

#thymeleaf的视图解析器
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
#定义shiro的加密算法
shiro.hashAlgorithmName=MD5
shiro.hashIterations=1024

1.4.创建实体类

@Data
public class Permission {
    @TableId(type = IdType.AUTO)
    private Integer perid;
    private String pername;
    private String percode;
}
@Data
public class User implements Serializable {

    @TableId(type = IdType.AUTO)
    private Integer userid;
    private String username;
    private String userpwd;
    private String sex;
    private String address;
    private String salt;
}

1.5.创建dao层

public interface UserDao extends BaseMapper<User> {
}

开启扫描dao包

1.6.创建service层

public interface UserService {
    public User findByUsername(String username);
}



@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public User findByUsername(String username) {
        // 创建一个查询条件包装器
        QueryWrapper<User> wrapper = new QueryWrapper<>();

        // 设置查询条件为"username = username"
        wrapper.eq("username", username);

        // 使用查询条件执行查询操作,返回单个用户对象
        User user = userDao.selectOne(wrapper);
        return user;
    }
}

1.7.编写realm

public class MyRealm extends AuthorizingRealm {

    @Autowired
    protected UserService userService;

    // 授权--权限
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 在此处添加授权逻辑
        return null;
    }

    //认证 -- 登录
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 1. 获取登录账号
        String username = token.getPrincipal().toString();

        // 2. 根据账号获取用户信息
        User user = userService.findByUsername(username);
        if (user != null) {
            // 使用用户的盐值创建 ByteSource 对象
            ByteSource salt = ByteSource.Util.bytes(user.getSalt());

            // 创建 SimpleAuthenticationInfo 对象,包含用户信息、密码、盐值和 Realm 名称
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getUserpwd(), salt, this.getName());
            return info;
        }
        // 用户不存在,返回 null
        return null;
    }
}

1.8.创建vo层

@Data
public class LoginVo {
    private String Password;
    private String Username;
}

1.9.创建Controller层

@Controller
public class LoginController {

    @PostMapping("/login")
    public String login(LoginVo loginVo) {
        // 获取当前主体对象
        Subject subject = SecurityUtils.getSubject();

        // 创建用户名密码令牌
        UsernamePasswordToken token = new UsernamePasswordToken(loginVo.getUsername(), loginVo.getPassword());

        try {
            // 调用主体的登录方法进行认证
            subject.login(token);

            // 登录成功,返回成功标识
            return "success";
        } catch (Exception e) {
            e.printStackTrace();

            // 登录失败,重定向到登录页面
            return "redirect:/login.html";
        }
    }

}

1.10. 创建shiro的配置类

----(相当于ssm中的spring配置文件)

package com.wqg.config;

import com.wqg.realm.MyRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

/**
 * @ fileName:ShiroConfig
 * @ description:
 * @ author:wqg
 * @ createTime:2023/7/7 16:33
 */
@Configuration
public class ShiroConfig {

    @Bean
    public DefaultWebSecurityManager securityManager() {
        // 创建默认的 Web 安全管理器
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置安全管理器使用的 Realm
        securityManager.setRealm(myRealm());
        // 返回安全管理器
        return securityManager;
    }

    @Bean
    public MyRealm myRealm(){
        MyRealm myRealm=new MyRealm();
        //设置密码加密器
        myRealm.setCredentialsMatcher(credentialsMatcher());
        return myRealm;
    }

    @Value("${shiro.hashAlgorithmName}")
    private String hashAlgorithmName;
    @Value("${shiro.hashIterations}")
    private int hashIterations;
    @Bean
    public HashedCredentialsMatcher credentialsMatcher() {
        // 创建密码匹配器对象
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();

        // 设置密码算法名称
        credentialsMatcher.setHashAlgorithmName(hashAlgorithmName);

        // 设置哈希迭代次数
        credentialsMatcher.setHashIterations(hashIterations);

        // 返回密码匹配器对象
        return credentialsMatcher;
    }


    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean factoryBean() {
        // 创建 Shiro 过滤器工厂 Bean
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager());

        // 设置登录页面的 URL
        shiroFilterFactoryBean.setLoginUrl("/login.html");

        // 设置过滤规则
        Map<String, String> map = new HashMap<>();
        // 指定 /login URL 不需要进行认证
        map.put("/login", "anon");
        // 其他 URL 需要进行认证
        map.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        // 返回 Shiro 过滤器工厂 Bean
        return shiroFilterFactoryBean;
    }


    //springboot如何注册web三大组件。
    @Bean
    public FilterRegistrationBean<Filter> filterRegistrationBean() {
        // 创建过滤器注册Bean对象
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();

        // 设置过滤器为DelegatingFilterProxy
        filterRegistrationBean.setFilter(new DelegatingFilterProxy());

        // 设置过滤器名称
        filterRegistrationBean.setName("shiroFilter");

        // 添加过滤器的URL模式,匹配所有URL
        filterRegistrationBean.addUrlPatterns("/*");

        // 返回过滤器注册Bean对象
        return filterRegistrationBean;
    }

}

1.11.创建登录页面与登录成功页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form action="/login" method="post">
  姓名:<input type="text" name="username" /><br><br>
  密码:<input type="text" name="password"/><br><br>
  <input type="submit" value="登录"/>
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登录成功~~~
</body>
</html>

1.12.测试

2.springboot整合shiro--授权(权限)

2.1.修改Realm

    @Autowired
    protected PermissionService permissionService;

    // 授权--权限
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 获取主体中的用户对象
        User user = (User) principals.getPrimaryPrincipal();

        // 根据用户ID查询用户权限列表
        List<String> list = permissionService.selectPermissionByUserid(user.getUserid());

        // 如果权限列表不为空
        if (list.size() != 0) {
            // 创建 SimpleAuthorizationInfo 对象
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

            // 将权限列表添加到授权信息中
            info.addStringPermissions(list);

            // 返回授权信息
            return info;
        }
        // 返回空,表示无授权信息
        return null;
    }

2.2.创建Service

public interface PermissionService {
    public List<String> selectPermissionByUserid(Integer userid);
}
@Service
public class PermissionServiceImpl implements PermissionService {
    @Autowired
    private PermissionDao permissionDao;

    @Override
    public List<String> selectPermissionByUserid(Integer userid) {
        // 根据用户ID查询用户权限列表
        List<Permission> permissionList = permissionDao.findPermissionByUserid(userid);

        // 使用流操作将权限列表中的每个权限对象映射为权限编码,并收集为新的列表
        List<String> collect = permissionList.stream().map(Permission::getPercode).collect(Collectors.toList());

        // 返回权限编码列表
        return collect;
    }

}

2.3.创建PermissionDao 

@Mapper
public interface PermissionDao extends BaseMapper<Permission> {
    List<Permission> findPermissionByUserid(Integer userid);
}

2.4.创建PermissionDao.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" >
<mapper namespace="com.wqg.dao.PermissionDao">

    <select id="findPermissionByUserid" resultType="com.wqg.entity.Permission">
        select p.* from user_role ur join role_permission rp on ur.roleId=rp.roleid
                                     join permission p on rp.perid=p.perid where ur.userid=#{userId}
    </select>
</mapper>

2.5.创建UserController

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/query")
    @RequiresPermissions(value = {"user:query","user:delete"},logical = Logical.OR) //可以通过多个路径访问内部资源
    //@RequiresPermissions(value = "user:query")
    public String query(){
        return "user:query------------------------";
    }

    @GetMapping("/update")
    @RequiresPermissions(value = "user:update")
    public String update(){
        return "user:update------------------------";
    }

    @GetMapping("/delete")
    @RequiresPermissions(value = "user:delete")
    public String delete(){
        return "user:delete------------------------";
    }

    @GetMapping("/insert")
    @RequiresPermissions(value = "user:insert")
    public String insert(){
        return "user:insert------------------------";
    }

    @GetMapping("/export")
    @RequiresPermissions(value = "user:export") //该注解不能被识别
    public String export(){
        return "user:export------------------------";
    }
}

2.6.修改登录成功页面

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro" >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
登录成功~~~
<h1 shiro:hasPermission="user:insert">
    <a href="/user/insert">增</a>
</h1>
<h1 shiro:hasPermission="user:delete">
    <a href="/user/delete">删</a>
</h1>
<h1 shiro:hasPermission="user:update">
    <a href="/user/update">改</a>
</h1>
<h1 shiro:hasPermission="user:query">
    <a href="/user/query">查</a>
</h1>
</body>
</html>

2.7.添加依赖

<!--shrio和thymeleaf集成的扩展依赖,为了能在页面上使用xsln:shrio的标签 -->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

2.8.ShiroConfig修改

 /**
     * 这里是为了能在html页面引用shiro标签,
     */ 
 @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {
        // 创建 Shiro 方言对象,用于在 Thymeleaf 中集成 Shiro 标签
        return new ShiroDialect();
    }

测试

 2.9.权限不足时跳转到一个页面

未跳转:

 实现跳转:

创建MyExceptionHandler

@ControllerAdvice
@Slf4j
public class MyExceptionHandler {

    @ExceptionHandler(value = AuthorizationException.class)
    public String authorizationException(Exception e){
        log.error("异常的内容====="+e.getMessage());
        return "403" ;
    }

}

创建403.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
权限不足~~~~
</body>
</html>

测试

3.springboot整合shiro----前后端分离

创建Result 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
    private Integer code;
    private String msg;
    private Object data;
}

3.1.登录成功或失败---返回json数据

 修改LoginController

测试:

3.2.权限不足时---返回json数据

修改MyExceptionHandler

测试

3.3.未登录时---返回json数据

添加依赖

<!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

创建LoginFilter

public class LoginFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        //设置响应的内容类型为JSON,并使用UTF-8编码
        response.setContentType("application/json;charset=utf-8");

        // 获取用于写入响应的PrintWriter对象
        PrintWriter writer = response.getWriter();

        // 创建一个Result对象,包含401状态码和提示信息
        Result result = new Result(401, "请先登录---", null);

        // 将Result对象转换为JSON字符串
        String jsonString = JSON.toJSONString(result);

        // 将JSON字符串写入响应
        writer.println(jsonString);

        // 刷新并关闭PrintWriter对象
        writer.flush();
        writer.close();

        // 返回false,表示请求应在此处停止
        return false;
    }
}

修改ShiroConfig

 测试,不登录,直接访问:

 4.shiro权限对象缓存到redis中

引入依赖

 <!--shiro和redis整合的依赖-->
        <dependency>
            <groupId>org.crazycake</groupId>
            <artifactId>shiro-redis</artifactId>
            <version>3.3.1</version>
        </dependency>

修改 ShiroConfig

 测试

5.使用Swagger2接口文档测试

引入依赖

  <!--swagger的依赖引入-->
        <dependency>
            <groupId>io.github.jianzhichun</groupId>
            <artifactId>spring-boot-starter-swagger2</artifactId>
            <version>0.0.1</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>

创建swagger配置文件



import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;


@Configuration  //swagger配置文件
public class SwaggerConfig {


    @Bean     //加在方法上,表示把方法的返回结果交于spring容器来管理该对象,里面封装了接口文档的信息
    public Docket docket() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName("qy165第五组")
                .apiInfo(getInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.wqg.controller"))
                .build();

        return docket;
    }

    private ApiInfo getInfo() {
        Contact DEFAULT_CONTACT = new Contact("张三", "151******", "319***7594@qq.com");
        ApiInfo apiInfo = new ApiInfo("学生管理系统API文档", "学生管理系统API文档",
                "2.0", "http://localhost:8080/doc.html", DEFAULT_CONTACT,
                "游戏公司", "www.4399.com");
        return apiInfo;
    }
}

设置放行

 测试http://localhost:8080/doc.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值