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"; // 返回访客视图
    }
}
相关推荐
Red Red4 小时前
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务
网络·笔记·学习·安全·web安全
2401_857610035 小时前
SpringBoot社团管理:安全与维护
spring boot·后端·安全
弗锐土豆7 小时前
工业生产安全-安全帽第二篇-用java语言看看opencv实现的目标检测使用过程
java·opencv·安全·检测·面部
HackKong8 小时前
小白怎样入门网络安全?
网络·学习·安全·web安全·网络安全·黑客
打码人的日常分享8 小时前
商用密码应用安全性评估,密评整体方案,密评管理测评要求和指南,运维文档,软件项目安全设计相关文档合集(Word原件)
运维·安全·web安全·系统安全·规格说明书
爱吃奶酪的松鼠丶8 小时前
Web安全之XSS攻击的防范
安全·web安全·xss
东莞梦幻网络科技软件开发公司8 小时前
开发体育赛事直播平台防止数据泄露的技术安全方案
经验分享·安全
vmlogin虚拟多登浏览器8 小时前
虚拟浏览器可以应对哪些浏览器安全威胁?
服务器·网络·安全·跨境电商·防关联
澜世8 小时前
2024小迪安全基础入门第三课
网络·笔记·安全·网络安全
.Ayang10 小时前
tomcat 后台部署 war 包 getshell
java·计算机网络·安全·web安全·网络安全·tomcat·网络攻击模型