在springboot 中使用shiro

一、导入shiro的依赖
在pow.xml文件中添加以下依赖
在这里插入图片描述
可复制以下代码

<!-- 引入shiro -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.4.0</version>
		</dependency>

二、在以下的项目结构下添加配置类和realm类
在这里插入图片描述
1、realm类内容

package com.woniuxy.realm;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import com.woniuxy.entity.User;
import com.woniuxy.service.UserService;

public class MyRealm extends AuthorizingRealm{
	//注入一个service,这个service通过账号查询信息
	@Autowired
	UserService userService;
	//用来从数据库中获取角色、权限的信息
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		System.out.println("正在获取角色权限信息。。。");
		//通过当前用户的账号去数据库中查询出当前用户的角色信息
		
		//假设通过账号找到了角色的信息,一个用户可以有多个角色
		Set<String> roles = new HashSet<>();
		roles.add("student");
		
		//通过角色查询角色对应的权限
		Set<String> perms = new HashSet<>();
		perms.add("student:del");
		
		//授权info
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setRoles(roles);
		info.setStringPermissions(perms);
		return info;
	}
	//获取认证(判断账号密码)的信息(账号密码)
	//如果这个方法返回null,表示没找到对应的账号,shiro就会报账号不存在异常
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		System.out.println("====================");
		System.out.println("正在进行认证...");
		System.out.println("====================");
		
		//获取账号,然后通过账号作为查询条件到数据库中查询账号信息(账号、密码等)
		String account = (String) token.getPrincipal();
		String pwd = new String((char[]) token.getCredentials());
		System.out.println(account+"..."+pwd);
		
		//调用serviece方法查询数据库
		User user = userService.findUserByAccount(account);
		//假设通过账号找到了一个信息
//		User user = new User().setAccount("admin").setPwd("123456");
		//创建认证info对象
		if(user==null) {
			return null;
		}
		SimpleAuthenticationInfo info = 
				new SimpleAuthenticationInfo(user.getAccount(),user.getPwd(),getName());
		return info;
	}

}

自己写的realm类需要继承AuthorizingRealm类,重写其中的两个方法:
doGetAuthorizationInfo:获取权限、角色信息
doGetAuthenticationInfo:获取认证(判断账号密码)的信息(账号密码)
2、配置类的内容:

package com.woniuxy.configuration;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.woniuxy.realm.MyRealm;

@Configuration//该注解表示当前类是一个配置类,作用与xml是一样的
public class ShiroConfiguration {
	//1、realm 域:作用用于从数据库中读取账号、角色、权限信息
	@Bean//该bean的ID就是下面的方法名
	public MyRealm myRealm() {
		return new MyRealm();
	}
	
	//2、securitymanager 安全管理器:shiro核心
	@Bean
	public SecurityManager securityManager(MyRealm myRealm) {//相当于<property name='' ref='myRealm'></property>
		DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
		manager.setRealm(myRealm);
		return manager;
	}
	
	//3、shiro的过滤器:指定哪些操作需要认证,需要指定的权限
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		//创建过滤器的工厂对象
		ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
		//设置安全管理器
		factoryBean.setSecurityManager(securityManager);
		//安全配置
		//设置登录页面
		factoryBean.setLoginUrl("/login.html");
		//没有权限时跳转到哪个页面
		factoryBean.setUnauthorizedUrl("/error.html");
		//认证成功之后跳转到指定的页面
		factoryBean.setSuccessUrl("/index.html");
		
		//******过滤器的配置******
		Map<String, String> map = new LinkedHashMap<>();//有序的map
		map.put("/index.html", "anon");//在登录/index.html 时 anon(匿名访问),不需要登录
		map.put("/login.html", "anon");
		map.put("/error.html", "anon");
		//放行静态资源
		map.put("/css/**", "anon");//表示放行css文件夹下的所有静态资源,/*代表当前目录下的文件,/**代表当前目录及其子目录的的文件
		map.put("/js/**", "anon");
		map.put("/html/**", "anon");
		map.put("/layui/**", "anon");
		map.put("/images/**", "anon");
		map.put("/videos/**", "anon");
		
		//动态请求放行
		map.put("/phase/**", "anon");
		map.put("/video/**", "anon");
		map.put("/user/login", "anon");
		
		
		/*
		 * 建议:能够用权限搞定的,就不要用角色。
		 */
		//权限设置访问url的角色
		map.put("/student.html", "roles[student]");
		map.put("/teacher.html", "roles[teacher]");
		
		//设置访问url的权限
		map.put("/student/del", "perms[student:del]");
		
		//注销
		map.put("/logout", "logout");
		//除开以上的,其他的都需要认证
		map.put("/**", "authc");//authc 认证authentication
		
		//将map赋值给shiro过滤器
		factoryBean.setFilterChainDefinitionMap(map);
		return factoryBean;
	}
}

在配置类中配置了shiro的三个重要部分:
realm域:是需要自己写的,也就是创建的realm类。
安全管理器(securitymanager):shiro自己有的,其中有一个属性是realm域,所以需要将自己写的realm域作为参数传入,目的是为其赋值。
shiro过滤器(ShiroFilter):shiro自己创建(通过工厂模式创建),过滤器中有一个属性行安全管理器,所以需要将安全管理器作为参数传入,目的也是为其赋值。

三、使用shiro,登录时的认证

@Controller
@RequestMapping("/user")
public class UserController {
	@RequestMapping("/login")
	@ResponseBody
	public Result<Object> login(User user, String captcha) {
		System.out.println(user);

		// 认证
		// 1、获取subject对象
		Subject currentUser = SecurityUtils.getSubject();
		Result<Object> result = new Result<>();
		// 2、判断是否认证过
		if (!currentUser.isAuthenticated()) {
			// 没认证,创建令牌(令牌携带账号密码)
			UsernamePasswordToken token = new UsernamePasswordToken(user.getAccount(), user.getPwd());
			// 认证
			try {
				currentUser.login(token);
				// 不报异常
				System.out.println("认证成功");
				result.setStatus(Result.SUCCESS);
				return result;
			} catch (UnknownAccountException e) {
				System.out.println("账号不存在");
				result.setStatus(Result.ERROR);
				result.setMessage("账户不存在!");
				return result;
			} catch (IncorrectCredentialsException e) {
				System.out.println("密码错误");
				result.setStatus(Result.ERROR);
				result.setMessage("密码错误!");
				return result;
			} catch (Exception e) {
				System.out.println("其他异常");
				result.setStatus(Result.ERROR);
				result.setMessage("网络繁忙,请稍后再试!");
				return result;
			}
		}
		return result.setStatus(Result.ERROR).setMessage("你已经登录过了!");
	}
}

四、在配置类中的过滤器总写请求需要的角色,权限等比较繁琐,可以通过注解的方式实现
1、在配置类中添加以下代码

//注解
	@Bean
	public AuthorizationAttributeSourceAdvisor 
	createAasa(SecurityManager securityManager) {
	        AuthorizationAttributeSourceAdvisor aasa
	            = new AuthorizationAttributeSourceAdvisor();
	        aasa.setSecurityManager(securityManager);
	        return aasa;
	}
	//注解aop
	@Bean
	@ConditionalOnMissingBean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
	        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
	        defaultAAP.setProxyTargetClass(true);
	        return defaultAAP;
	}

2、注解的使用

	//@RequiresRoles("student")//要求有student角色的人才能访问这个请求
	//@RequiresRoles(value={"student","teacher"},logical=Logical.OR)//要求具备学生或者老师角色的用户可以访问这个请求
	//@RequiresRoles(value= {"student","teacher"})//要求同时具有老师和学生角色的用户才可以使用该请求,logical(逻辑)不写默认为Logical.AND
	//@RequiresPermissions("student:del")
	@RequestMapping("/all")
	@ResponseBody
	public List<Phase> all(){
		return phaseService.all();
	}
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Spring Boot项目使用Shiro实现接口授权,需要进行以下步骤: 1. 添加Shiro依赖 在pom.xml文件添加Shiro依赖: ``` <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.0</version> </dependency> ``` 2. 配置Shiro 在Spring Boot的配置文件添加Shiro的配置,如下所示: ``` shiro: filter-chain-definitions: /** = anon /login = anon /logout = logout /api/** = authc security-manager: realm: type: org.apache.shiro.realm.jdbc.JdbcRealm authentication-query: SELECT password FROM users WHERE username = ? user-roles-query: SELECT role_name FROM user_roles WHERE username = ? permissions-query: SELECT permission FROM roles_permissions WHERE role_name = ? ``` 该配置文件配置了Shiro的过滤链,以及Shiro的安全管理器和Realm。 3. 编写Shiro Realm 编写一个继承自JdbcRealm的Realm类,并实现doGetAuthenticationInfo()和doGetAuthorizationInfo()两个方法,如下所示: ``` public class MyRealm extends JdbcRealm { @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); String password = new String(upToken.getPassword()); // 根据用户名和密码查询数据库,如果查询到了用户,则返回一个封装了该用户信息的AuthenticationInfo对象 // 如果没有查询到用户,则返回null } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); String username = (String) principals.getPrimaryPrincipal(); // 根据用户名查询用户的角色和权限信息,并将其添加到authorizationInfo return authorizationInfo; } } ``` 4. 配置ShiroFilterFactoryBean 在Spring Boot的配置文件配置ShiroFilterFactoryBean,如下所示: ``` @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(@Autowired MyRealm myRealm) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(new DefaultWebSecurityManager(myRealm)); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/logout", "logout"); filterChainDefinitionMap.put("/api/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } ``` 该配置文件配置了一个ShiroFilterFactoryBean,并将其与安全管理器和过滤链绑定在一起。 5. 编写接口控制器 编写一个接口控制器,并在该控制器添加需要授权的接口方法,如下所示: ``` @RestController public class ApiController { @GetMapping("/api/hello") public String hello() { return "Hello, world!"; } @RequiresRoles("admin") @PostMapping("/api/admin") public String admin() { return "Hello, admin!"; } } ``` 上述代码,hello()方法不需要授权,而admin()方法需要授予admin角色才能访问。 6. 测试接口授权 启动Spring Boot应用程序,并使用curl或Postman等工具测试接口授权。例如,可以使用以下命令测试admin接口: ``` curl -X POST http://localhost:8080/api/admin -H 'Authorization: Basic YWRtaW46YWRtaW4=' ``` 其,Authorization头的值是用户名和密码的Base64编码,上述例子的用户名和密码都是admin。如果授权成功,服务器将返回"Hello, admin!"。如果授权失败,则返回401 Unauthorized错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值