Shiro认证和授权

shiro是一款权限控制的后台框架,可以控制用户-角色-权限的分配,例如资源和路径等等。

主要内容:

ShiroFilterFactoryBean工厂类

SecurityManager安全管理器

MyRealm extends AuthorizingRealm自定义Realm,实现doGetAuthenticationInfo(认证)和doGetAuthorizationInfo(授权)方法。

还有其他一些rememberMe、Session和Cache功能。

下面使用SpringBoot整合Shiro的例子简单说明

表:数据中用户密码要存储加密后的密文

45a52174bec71570e89096a5b180394d24e.jpg

pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>online.myson</groupId>
	<artifactId>shiro</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>Shiro</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- shiro -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.4.0</version>
		</dependency>
		<!-- Spring Data JPA -->
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-data-jpa</artifactId>
		    <version>2.0.1.RELEASE</version>
		</dependency>
		<!-- mysql -->
		<dependency>
		    <groupId>mysql</groupId>
		    <artifactId>mysql-connector-java</artifactId>
		    <version>5.1.45</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

shiro配置类

package online.myson.config;

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

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.SimpleHash;
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.util.ByteSource;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import online.myson.shiro.MyRealm;

@Configuration
public class ShiroConfig {

	/**
	 * 注册ShiroFilterFactoryBean,其实是注册一个filter
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
		
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		// 设置securityManager
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		
		// 设置拦截器
		Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
		// 过滤链定义,从上向下执行,一般将/**放最下面
		// authc:所有的url都必须认证通过才可以访问;anon:所有url都可以匿名访问
		filterChainDefinitionMap.put("/statics/**", "anon");
		filterChainDefinitionMap.put("/login.html", "anon");
		filterChainDefinitionMap.put("/login", "anon");
		filterChainDefinitionMap.put("/user/**", "user");
		filterChainDefinitionMap.put("/*", "authc");
		// 不设置自动寻找根目录下的/login.jsp页面
		shiroFilterFactoryBean.setLoginUrl("/index");
		
		// 登录成功后要跳转的连接
		shiroFilterFactoryBean.setSuccessUrl("/index");
		
		// 未授权页面
		shiroFilterFactoryBean.setUnauthorizedUrl("/403");
		
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;	
	}
	
	/**
	 * 注册securityManager
	 */
	@Bean
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(myRealm());
		securityManager.setRememberMeManager(cookieRememberMeManager());
		return securityManager;
	}
	
	/**
	 * 注册自定义Realm
	 */
	@Bean
	public MyRealm myRealm() {
		MyRealm myRealm = new MyRealm();
		myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return myRealm;
	}
	
	/**
	 * 注册HashedCredentialsMatcher,加解密
	 */
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		
		hashedCredentialsMatcher.setHashAlgorithmName("md5");
		hashedCredentialsMatcher.setHashIterations(2);
		
		return hashedCredentialsMatcher;
		
	}
	
	/**
	 * 注册CookieRememberMeManager
	 */
	@Bean
	public CookieRememberMeManager cookieRememberMeManager() {
		CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
		cookieRememberMeManager.setCookie(simpleCookie());
		return cookieRememberMeManager;
	}
	
	/**
	 * 注册SimpleCookie
	 */
	@Bean
	public SimpleCookie simpleCookie() {
		SimpleCookie simpleCookie = new SimpleCookie();
		simpleCookie.setPath("/");
		simpleCookie.setHttpOnly(true);
		simpleCookie.setMaxAge(604800);// 时间
		return simpleCookie;
	}
	
	/**
	 * 开启shiro aop支持
	 * 用于授权
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor AuthorizationAttributeSourceAdvisor(
			SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor
						= new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}
	
	public static void main(String[] args) {
		Object obj = new SimpleHash("md5","123456",ByteSource.Util.bytes("user"),2);
		System.out.println(obj);
	}
}

 

1、认证

    // 认证
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// 获取用户输入的账号
		String username = (String)token.getPrincipal();
		System.out.println(token.getCredentials());
		
		// 查询是否存在账号
		SysUser user = sysUserService.findByUsername(username);
		System.out.println(user);
		if(user == null) {
			return null;
		}
		
		// 验证密码
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
					user,
					user.getPassword(),
					ByteSource.Util.bytes(user.getSalt()),// salt
					"MyRealm"// realmName
				);
		
		return authenticationInfo;
	}

Controller类:

    @PostMapping("/login")
	public ModelAndView login(SysUser user) {
		ModelAndView mv = new ModelAndView("/login");
		String msg = "成功";
		
		Subject subject = SecurityUtils.getSubject();
		
		UsernamePasswordToken token = 
				new UsernamePasswordToken(user.getUsername(), user.getPassword());
		
		try {
			subject.login(token);
		}catch(Exception e) {
			if(e instanceof UnknownAccountException) {
				msg = "账户不存在";
			}else if(e instanceof IncorrectCredentialsException) {
				msg = "密码不正确";
			}else {
				msg = e.getMessage();
			}
		}
		
		mv.addObject("msg", msg);
		return mv;
	}

2、授权

三种方式:

a、通过Subject.isPermitted("userInfo:view")和subject.hasRole("admin")的一些方法,if else来控制

b、通过注解AOP控制

c、jsp页面使用标签<shiro>控制

    // 授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		SysUser user = (SysUser) principals.getPrimaryPrincipal();
		
		// 获取用户的角色和对应的权限,这里一次性查角色和权限了,也可以写sql查
		for(SysRole role : user.getRoleList()) {
			authorizationInfo.addRole(role.getRole());
			for(SysPermission permission : role.getPermissions()) {
				authorizationInfo.addStringPermission(permission.getPermission());
			}
		}
		
		return authorizationInfo;
	}

Controller:

/**
	 * 用户添加
	 */
	@GetMapping("/user/add")
	@RequiresPermissions("userInfo:view")
	public String userAdd() {
		Subject subject = SecurityUtils.getSubject();
//		if(subject.isPermitted("userInfo:view")) {
//			return "userAdd";
//		}else {
//			return "no authc";
//		}
		return "userAdd";

 

转载于:https://my.oschina.net/u/3494913/blog/2354630

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shiro框架是一个功能强大的Java安全框架,可以用于认证授权。下面是使用Shiro进行认证授权的基本步骤: 1. 添加Shiro依赖:在你的项目中添加Shiro的相关依赖,可以通过Maven或者Gradle进行引入。 2. 配置Shiro:创建一个Shiro的配置文件(通常是一个ini文件),配置Shiro的一些基本信息,例如Realm、Session管理等。你可以根据你的需求进行配置。 3. 创建Realm:Realm是Shiro用来进行认证授权的核心组件。你需要实现一个自定义的Realm来实现用户的认证授权逻辑。在Realm中,你可以通过重写相应的方法来实现自定义的认证授权逻辑,例如验证用户名密码、查询用户角色和权限等。 4. 认证:在用户登录时,你可以通过调用Shiro提供的Subject.login方法来进行认证。该方法会将用户提交的用户名和密码传递给你自定义的Realm进行验证。如果验证通过,Shiro会将用户信息保存在Session中。 5. 授权:在用户进行操作时,你可以通过调用Shiro提供的Subject.hasRole和Subject.isPermitted方法来进行授权判断。这些方法会根据你在Realm中配置的角色和权限信息进行判断,决定用户是否具有相应的角色或权限。 以上是使用Shiro进行认证授权的基本步骤,你可以根据具体的需求进行定制和扩展。在实际应用中,你还可以通过Shiro提供的其他功能,如RememberMe、Session管理等来增强安全性和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值