【Shiro从入门到精通】——一篇文章让小白也能快速了解并掌握基础Shiro知

org.apache.shiro

shiro-core

1.4.1

org.slf4j

slf4j-simple

1.7.21

test

org.slf4j

jcl-over-slf4j

1.7.21

test

我们将使用 INI 文件为该简单应用程序配置 Shiro SecurityManager。首先,从pom.xml所在的目录创建一个 src/main/resources 目录。然后在新目录中创建一个shiro.ini文件,其内容如下:

# =============================================================================

# Tutorial INI configuration

#

# Usernames/passwords are based on the classic Mel Brooks' film "Spaceballs" :)

# =============================================================================

# -----------------------------------------------------------------------------

# Users and their (optional) assigned roles

# username = password, role1, role2, ..., roleN

# -----------------------------------------------------------------------------

[users]

root = secret, admin

guest = guest, guest

presidentskroob = 12345, president

darkhelmet = ludicrousspeed, darklord, schwartz

lonestarr = vespa, goodguy, schwartz

# -----------------------------------------------------------------------------

# Roles with assigned permissions

# roleName = perm1, perm2, ..., permN

# -----------------------------------------------------------------------------

[roles]

admin = *

schwartz = lightsaber:*

goodguy = winnebago:drive:eagle5

此配置基本上设置了一小组静态用户帐户,足以满足我们的第一个应用程序的需要。在后面的章节中,您将看到我们如何使用关系数据库,LDAP 和 ActiveDirectory 等更复杂的 User 数据源。

现在已经定义了一个 INI 文件,我们可以在 Tutorial 应用程序类中创建SecurityManager实例。更改main方法以反映以下更新:

public static void main(String[] args) {

log.info("My First Apache Shiro Application");

//1.

Factory factory = new IniSecurityManagerFactory("classpath:shiro.ini");

//2.

SecurityManager securityManager = factory.getInstance();

//3.

SecurityUtils.setSecurityManager(securityManager);

System.exit(0);

}

随意运行mvn compile exec:java并查看一切仍可成功运行(由于 Shiro 的默认调试日志记录或更低版本,您将看不到任何 Shiro 日志消息-如果它启动并运行无错误,则说明一切仍然正常)。

现在我们的 SecurityManager 已经设置好并且可以使用了,现在我们可以开始做我们 true 关心的事情了-执行安全操作。

🎯SpringBoot集成Shiro

😎准备工作

导入

Maven依赖thymeleaf

org.thymeleaf

thymeleaf-spring5

org.thymeleaf.extras

thymeleaf-extras-java8time

编写一个页面

index.html templates

Title

首页

编写

controller

进行访问测试

package com.kuang.controller;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

public class MyController {

@RequestMapping({"/","/index"})

public String toIndex(Model model){

model.addAttribute("msg","hello,Shiro");

return "index";

}

}

thymeleaf

😎整合Shiro

导入Shiro 和 spring整合的依赖

org.apache.shiro

shiro-spring

1.4.1

编写

Shiro

配置类 config包

package com.kuang.config;

import org.springframework.context.annotation.Configuration;

//声明为配置类

@Configuration

public class ShiroConfig {

//创建 ShiroFilterFactoryBean

//创建 DefaultWebSecurityManager

//创建 realm 对象

}

创建一个 realm 对象

package com.kuang.config;

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authz.AuthorizationInfo;

import org.apache.shiro.realm.AuthorizingRealm;

import org.apache.shiro.subject.PrincipalCollection;

//自定义Realm

public class UserRealm extends AuthorizingRealm {

//执行授权逻辑

@Override

protected AuthorizationInfo

doGetAuthorizationInfo(PrincipalCollection principals) {

System.out.println("执行了=>授权逻辑PrincipalCollection");

return null;

}

//执行认证逻辑

@Override

protected AuthenticationInfo

doGetAuthenticationInfo(AuthenticationToken token) throws

AuthenticationException {

System.out.println("执行了=>认证逻辑AuthenticationToken");

return null;

}

}

将这个类注册到我们的Bean中! ShiroConfig

@Configuration

public class ShiroConfig {

//创建 ShiroFilterFactoryBean

//创建 DefaultWebSecurityManager

//创建 realm 对象

@Bean

public UserRealm userRealm(){

return new UserRealm();

}

}

接下来我们该去创建 DefaultWebSecurityManager 了

//创建 DefaultWebSecurityManager

@Bean(name = "securityManager")

public DefaultWebSecurityManager

getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){

DefaultWebSecurityManager securityManager = new

DefaultWebSecurityManager();

//关联Realm

securityManager.setRealm(userRealm);

return securityManager;

}

接下来我们该去创建 ShiroFilterFactoryBean 了

//创建 ShiroFilterFactoryBean

@Bean

public ShiroFilterFactoryBean

getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurity

Manager securityManager){

ShiroFilterFactoryBean shiroFilterFactoryBean = new

ShiroFilterFactoryBean();

//设置安全管理器

shiroFilterFactoryBean.setSecurityManager(securityManager);

return shiroFilterFactoryBean;

}

最后上完整的配置:

package com.kuang.config;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;

import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

//声明为配置类

@Configuration

public class ShiroConfig {

//创建 ShiroFilterFactoryBean

@Bean

public ShiroFilterFactoryBean

getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityMan

ager securityManager){

ShiroFilterFactoryBean shiroFilterFactoryBean = new

ShiroFilterFactoryBean();

//设置安全管理器

shiroFilterFactoryBean.setSecurityManager(securityManager);

return shiroFilterFactoryBean;

}

//创建 DefaultWebSecurityManager

@Bean(name = "securityManager")

public DefaultWebSecurityManager

getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){

DefaultWebSecurityManager securityManager = new

DefaultWebSecurityManager();

//关联Realm

securityManager.setRealm(userRealm);

return securityManager;

}

//创建 realm 对象

@Bean

public UserRealm userRealm(){

return new UserRealm();

}

}

😎页面拦截实现

跳转到页面的

controller

@RequestMapping("/user/add")

public String toAdd(){

return "user/add";

}

@RequestMapping("/user/update")

public String toUpdate(){

return "user/update";

}

添加Shiro的内置过滤器

@Bean

public ShiroFilterFactoryBean

getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurit

yManager securityManager){

ShiroFilterFactoryBean shiroFilterFactoryBean = new

ShiroFilterFactoryBean();

//设置安全管理器

shiroFilterFactoryBean.setSecurityManager(securityManager);

/*

添加Shiro内置过滤器,常用的有如下过滤器:

anon: 无需认证就可以访问

authc: 必须认证才可以访问

user: 如果使用了记住我功能就可以直接访问

perms: 拥有某个资源权限才可以访问

role: 拥有某个角色权限才可以访问

*/

Map filterMap = new LinkedHashMap();

filterMap.put("/user/add","authc");

filterMap.put("/user/update","authc");

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

return shiroFilterFactoryBean;

}

🎯登录认证操作

编写一个登录的

controller

//登录操作

@RequestMapping("/login")

public String login(String username,String password,Model model){

//使用shiro,编写认证操作

//1. 获取Subject

Subject subject = SecurityUtils.getSubject();

//2. 封装用户的数据

UsernamePasswordToken token = new UsernamePasswordToken(username,

password);

//3. 执行登录的方法,只要没有异常就代表登录成功!

try {

subject.login(token); //登录成功!返回首页

return "index";

} catch (UnknownAccountException e) { //用户名不存在

model.addAttribute("msg","用户名不存在");

return "login";

} catch (IncorrectCredentialsException e) { //密码错误

model.addAttribute("msg","密码错误");

return "login";

}

}

UserRealm

中编写用户认证的判断逻辑

//执行认证逻辑

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken

token) throws AuthenticationException {

System.out.println("执行了=>认证逻辑AuthenticationToken");

//假设数据库的用户名和密码

String name = "root";

String password = "123456";

//1.判断用户名

UsernamePasswordToken userToken = (UsernamePasswordToken)token;

if (!userToken.getUsername().equals(name)){

//用户名不存在

return null; //shiro底层就会抛出 UnknownAccountException

}

//2. 验证密码,我们可以使用一个AuthenticationInfo实现类

SimpleAuthenticationInfo

// shiro会自动帮我们验证!重点是第二个参数就是要验证的密码!

return new SimpleAuthenticationInfo("", password, "");

}

🎯整合数据库

导入

Mybatis

相关依赖

org.mybatis.spring.boot

mybatis-spring-boot-starter

2.1.0

mysql

mysql-connector-java

runtime

log4j

log4j

1.2.17

com.alibaba

druid

1.1.12

改造

UserRealm

,连接到数据库进行真实的操作!

//自定义Realm

public class UserRealm extends AuthorizingRealm {

@Autowired

UserService userService;

//执行授权逻辑

@Override

protected AuthorizationInfo

doGetAuthorizationInfo(PrincipalCollection principals) {

System.out.println("执行了=>授权逻辑PrincipalCollection");

return null;

}

//执行认证逻辑

@Override

protected AuthenticationInfo

doGetAuthenticationInfo(AuthenticationToken token) throws

AuthenticationException {

System.out.println("执行了=>认证逻辑AuthenticationToken");

UsernamePasswordToken userToken = (UsernamePasswordToken)token;

//真实连接数据库

User user =

userService.queryUserByName(userToken.getUsername());

if (user==null){

//用户名不存在

return null; //shiro底层就会抛出 UnknownAccountException

}

return new SimpleAuthenticationInfo("", user.getPwd(), "");

}

}

🎯Shiro授权

UserRealm

中添加授权的逻辑,增加授权的字符串!

//执行授权逻辑

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection

principals) {

System.out.println("执行了=>授权逻辑PrincipalCollection");

//给资源进行授权

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

//添加资源的授权字符串

info.addStringPermission("user:add");

return info;

}

我们再次登录测试,发现登录的用户是可以进行访问

add

页面了!授权成功!

🎯整合Thymeleaf

添加

Maven

的依赖;

com.github.theborakompanioni

thymeleaf-extras-shiro

2.0.0

配置一个

shiro

Dialect

,在

shiro

的配置中增加一个

Bean

//配置ShiroDialect:方言,用于 thymeleaf 和 shiro 标签配合使用

@Bean

public ShiroDialect getShiroDialect(){

return new ShiroDialect();

}

为了完美,我们在用户登录后应该把信息放到Session

中,我们完善下!在执行认证逻辑时候,加 入session

Subject subject = SecurityUtils.getSubject();

subject.getSession().setAttribute("loginUser",user);

友情链接