SpringBoot整合Shiro - Go语言中文社区

SpringBoot整合Shiro


环境搭建

1、新建maven项目,导入依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.3.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring-boot-starter</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
        <version>2.2.3.RELEASE</version>
    </dependency>
</dependencies>

2、新建静态页面

resources/templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h1>首页</h1>
<hr>
<a href="/user/add">添加</a> | <a href="/user/update">修改</a>
</body>
</html>

resources/templates/login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<h1>用户登录</h1>
<hr>
<form action="/login" method="post">
    <span th:text="${msg}" style="color: red;"></span><br>
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <button type="submit">登录</button>
</form>
</body>
</html>

resources/templates/user/add.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>add</title>
</head>
<body>
<h1>添加用户</h1>
<hr>
</body>
</html>

resources/templates/user/update.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>修改</title>
</head>
<body>
<h1>修改用户信息</h1>
<hr>
</body>
</html>

3、 新建Controller

package com.qianyu.Controler;

import org.apache.shiro.*;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.*;
import org.springframework.stereotype.*;
import org.springframework.ui.*;
import org.springframework.web.bind.annotation.*;

@Controller
public class DemoController {
    @GetMapping({"/index", "/", "index.html"})
    public String index() {
        return "index";
    }

    @GetMapping("/user/add")
    public String add() {
        return "user/add";
    }

    @GetMapping("/user/update")
    public String upd() {
        return "user/update";
    }

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

4、新建主类和配置文件application.yml

package com.qianyu;

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
server:
  port: 9000
spring:
  thymeleaf:
    cache: false

整合Shiro

1、新建UserRealm类,用于对用户的认证和授权

package com.qianyu.config;

import jdk.nashorn.internal.parser.*;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.*;
import org.apache.shiro.realm.*;
import org.apache.shiro.subject.*;

public class UserRealm extends AuthorizingRealm {
    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权方法");
        return null;
    }

    // 认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了认证方法");
        // 用户名和密码,项目中应该从数据库取
        String username = "root";
        String password = "123456";

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        // 用户名认证
        if (!userToken.getUsername().equals(username)) {
            return null; // 抛出UnknownAccountException异常
        }
        // 密码认证
        return new SimpleAuthenticationInfo("", password, "");
    }
}

2、新建Shiro配置类

package com.qianyu.config;

import org.apache.commons.collections.map.*;
import org.apache.shiro.spring.web.*;
import org.apache.shiro.web.mgt.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.context.annotation.*;

import java.util.*;

@Configuration
public class ShiroConfig {
    // 1. 创建realm对象,需要自定义类
    @Bean
    public UserRealm userRealm() {
        return new UserRealm();
    }

    // 2. 创建DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        // 关联Realm对象
        manager.setRealm(userRealm);
        return manager;
    }

    // 3. 创建ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager manager) {
        // 设置安全过滤器
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(manager);
        // 添加shiro内置过滤器
        /**
         * anon:无需认证就可以访问
         * authc:必须认证了才能够访问
         * user:必须拥有“记住我”功能才能够访问
         * perms:拥有对某个资源的权限才能够访问
         * role:拥有某个角色权限才能够访问
         */
        LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/user/*", "authc");
        bean.setFilterChainDefinitionMap(filterMap);
        // 设置认证需要跳转的登录界面,如果不设置的话默认shiro会找login.jsp
        bean.setLoginUrl("/login");
        return bean;
    }
}

3、处理登录请求

@PostMapping("/login")
public String login(String username, String password, Model model) {
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    try {
        // 执行登录操作,执行过程我们在UserRealm中进行
        subject.login(token);
    } catch (UnknownAccountException e) {
        model.addAttribute("msg", "用户名错误");
        return "login";
    }catch (IncorrectCredentialsException e){
        model.addAttribute("msg", "密码错误");
        return "login";
    }
    return "index";
}

效果

未登录的情况下,点击“修改”或者“添加”,都会跳转到登录界面

首页

用户登录时,用户名或密码输入错误的话会给出相应提示:

错误提示

用户登录成功之后可以自由访问“添加”和“修改”页面

添加用户界面

整合Mybatis

1、导入依赖

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.19</version>
</dependency>

2、新建实体类

package com.qianyu.pojo;

import lombok.*;

@Data
public class UserDO {
    private Integer id;
    private String username;
    private String password;
    // 权限
    private String perms;
}

3、新建mapper

package com.qianyu.mapper;

import com.qianyu.pojo.*;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.*;

@Mapper
@Component
public interface UserMapper {
    @Select("select * from user where username=#{username}")
    UserDO getUserByName(@Param("username") String name);
}

4、配置文件

server:
  port: 9000
spring:
  thymeleaf:
    cache: false
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/qianyu?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: 111111
mybatis:
  type-aliases-package: com.qianyu.pojo
  configuration:
    map-underscore-to-camel-case: true

5、user表中数据如图所示

可见用户111111拥有插入权限,用户222222具有更新权限

数据表

6、修改UserRealm,注入UserMapper,在doGetAuthorizationInfo方法中拿到该用户的权限

package com.qianyu.config;

import com.qianyu.mapper.*;
import com.qianyu.pojo.*;
import org.apache.shiro.*;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.*;
import org.apache.shiro.realm.*;
import org.apache.shiro.subject.*;
import org.springframework.beans.factory.annotation.*;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserMapper userMapper;

    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // 拿到当前登录的对象
        Subject subject = SecurityUtils.getSubject();
        UserDO currentUser = (UserDO) subject.getPrincipal();
        // 设置当前用户的权限
        info.addStringPermission(currentUser.getPerms());
        return info;
    }

    // 认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        String username = userToken.getUsername();
        UserDO user = userMapper.getUserByName(username);
        // 用户名认证
        if (null == user) {
            return null; // 抛出UnknownAccountException异常
        }
        // 密码认证,这里传入user的目的是使用Subject可以获取到当前登录的用户对象
        return new SimpleAuthenticationInfo(user, user.getPassword(), "");
    }
}

7、修改ShiroConfig类中的shiroFilterFactoryBean方法,设置访问权限(也就是说,只有拥有这个权限的用户,才能访问此页面)

@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager manager) {
    // 设置安全过滤器
    ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
    bean.setSecurityManager(manager);
    // 添加shiro内置过滤器
    LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
    // 授权:授权失败的话跳转到未授权页面
    filterMap.put("/user/add", "perms[user:add]");
    filterMap.put("/user/update", "perms[user:update]");

    filterMap.put("/user/*", "authc");
    bean.setFilterChainDefinitionMap(filterMap);
    // 设置认证需要跳转的登录界面,如果不设置的话默认shiro会找login.jsp
    bean.setLoginUrl("/login");
    
                        
                        
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/li3455277925/article/details/104364732
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢