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"; // 返回访客视图
    }
}
相关推荐
网安-轩逸3 小时前
网络安全防御模型
安全·web安全·php
夏炎正好眠5 小时前
seacmsv9报错注入
安全
Hacker_xingchen8 小时前
网络安全扫描--基础篇
网络·安全·web安全
不爱学习的YY酱11 小时前
使用ZFile打造属于自己的私有云系统结合内网穿透实现安全远程访问
安全
网硕互联的小客服12 小时前
服务器硬件老化导致性能下降的排查与优化
linux·运维·服务器·安全·centos
网安CILLE14 小时前
自学网络安全(黑客技术)2025年 —90天学习计划
linux·网络·安全·web安全·网络安全
z2023050814 小时前
SOC-ATF 安全启动BL1流程分析(1)
安全
今晚打老虎z14 小时前
双重因子认证:守护数字安全的“双保险”
安全
黑客KKKing15 小时前
网络安全词汇
网络·算法·安全·web安全
燕雀安知鸿鹄之志哉.15 小时前
jdk21下载、安装(Windows、Linux、macOS)
网络·安全·web安全·网络安全·系统安全