Shiro安全认证技术实践

为Java后端项目添加Shiro进行身份验证,授权操作:

步骤1.引入相关依赖:

html 复制代码
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-spring-boot-starter</artifactId>
  <version>1.9.1</version> <!-- 确保使用最新版本 -->
</dependency>

步骤2.配置shiro.ini

在resources目录下进行添加shiro.ini文件

html 复制代码
[main]
# Realm配置
myRealm = org.apache.shiro.realm.jdbc.JdbcRealm
myRealm.dataSource = myDataSource

# 使用自定义Realm
securityManager.realms = $myRealm

[users]
# 用户名 = 密码, 角色
admin = secret, admin
guest = guest, guest

[roles]
# 角色 = 权限
admin = *
guest = read
user = read

步骤3.配置ShiroConfig

在config目录下创建ShiroConfig.java文件

java 复制代码
package com.cetide.oj.config;

import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Bean
    public Realm myRealm() {
        // 返回你自己的 Realm 实现
        return new MyRealm();
    }

    @Bean
    public ModularRealmAuthenticator authenticator() {
        ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
        authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        authenticator.setRealms(Arrays.asList(myRealm()));
        return authenticator;
    }

    @Bean
    public ModularRealmAuthorizer authorizer() {
        ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
        authorizer.setRealms(Arrays.asList(myRealm()));
        return authorizer;
    }
    @Bean
    public SecurityManager securityManager(DataSource dataSource) {
        JdbcRealm realm = new JdbcRealm();
        realm.setDataSource(dataSource);

        // 配置Realm的用户查询和角色查询
        realm.setPermissionsLookupEnabled(true); // 启用权限查找
        // 你可以在这里设置自定义的SQL查询以获取用户和角色信息

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);
        return securityManager;
    }

    @Bean
    public DefaultSessionManager sessionManager() {
        DefaultSessionManager sessionManager = new DefaultSessionManager();
        return sessionManager;
    }
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        filterFactoryBean.setSecurityManager(securityManager);

        // 配置访问路径
        Map<String, String> filterChainDefinitionMap = new HashMap<>();
        filterChainDefinitionMap.put("/admin/**", "roles[admin]");
        filterChainDefinitionMap.put("/guest/**", "roles[guest]");
        filterChainDefinitionMap.put("/**", "anon"); // 允许匿名访问
        filterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return filterFactoryBean;
    }
}

步骤4.配置自定义MyRealm

java 复制代码
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class MyRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        if ("admin".equals(username)) {
            info.addRole("admin");
            info.addStringPermission("*"); // admin有所有权限
        } else if ("guest".equals(username)) {
            info.addRole("guest");
            info.addStringPermission("read"); // guest仅有读取权限
        }
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());

        // 模拟数据库查询
        if ("admin".equals(username) && "123456".equals(password)) {
            return new SimpleAuthenticationInfo(username, password, getName());
        } else {
            throw new UnknownAccountException("用户名或密码错误");
        }
    }
}

步骤5.引入到Controller中

java 复制代码
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {
    @PostMapping("/login")
    public String login(String username, String password) {
        Subject currentUser = SecurityUtils.getSubject();

        if (!currentUser.isAuthenticated()) {
            // 创建一个用户认证的token
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            try {
                // 执行登录操作
                currentUser.login(token);
                if (currentUser.hasRole("admin")) {
                    return "admin"; // 返回管理员视图
                }
                return "403"; // 无权限视图
            } catch (Exception e) {
                e.printStackTrace();
                return "loginError"; // 登录失败,返回错误视图
            }
        }

        return "redirect:/"; // 已经登录,重定向到主页
    }

    @RequestMapping("/logout")
    public String logout() {
        Subject currentUser = SecurityUtils.getSubject();
        if (currentUser.isAuthenticated()) {
            currentUser.logout(); // 执行注销
        }
        return "redirect:/"; // 注销后重定向到主页
    }
    @GetMapping("/")
    public String home() {
        return "index"; // 返回主页视图
    }

    @GetMapping("/admin")
    public String admin() {
        Subject currentUser = SecurityUtils.getSubject();
        if (currentUser.hasRole("admin")) {
            return "admin"; // 返回管理员视图
        }
        return "403"; // 无权限视图
    }

    @GetMapping("/guest")
    public String guest() {
        return "guest"; // 返回访客视图
    }
}
相关推荐
天天进步201513 小时前
UI-TARS 源码解析 #10:parse_action 源码解析:如何用 AST 安全解析模型生成的函数调用?
安全·ui
大耳朵-小飞象15 小时前
电力安全运维的智能密码:BACS如何破解设备全生命周期管理难题,让电网安全“看得见、管得住”?
运维·安全·智慧城市·能耗系统·楼宇智控·未来生活
wuhanzhanhui17 小时前
视觉革命与主动安全:2026武汉汽车电子展会定档,看芯片如何定义驾驶
安全·汽车
王维同学19 小时前
[原创][Windows C++]LSA 认证、安全与通知包的注册表枚举
c++·windows·安全
国科安芯21 小时前
星间光链路:AS32S601型抗辐射MCU在空间激光通信终端控制中的技术实现
服务器·网络·单片机·嵌入式硬件·物联网·安全·信息与通信
栩栩云生1 天前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
huijingjituan1 天前
新一代IM聊天软件|构建企业专属智能通讯生态
安全·实时互动·即时通讯·极光鸟·灰鲸
其实防守也摸鱼1 天前
补天SRC新手入门指南:从0到1的漏洞挖掘之路
网络·python·学习·安全·web安全·数据挖掘·挖洞
●VON1 天前
鸿蒙 PC Markdown 编辑器内部隐私与安全评审
安全·华为·编辑器·harmonyos·鸿蒙
我不是QI1 天前
一、主持人信息(域名 网站资产情报搜集)原理解析
安全·网络安全