Springboot整合Shiro

375 阅读4分钟

1. 新建springboot工程

默认选中 lomback,spring web,Themlyf模块

2. 手动添加spring与shiro的整合包

<!--        手动添加shiro 我们添加的一定是 shiro与spring的整合包-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.5.3</version>
        </dependency>

创建数据库

CREATE TABLE `account` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `username` varchar(255) DEFAULT NULL COMMENT '用户名',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  `perms` varchar(255) DEFAULT NULL COMMENT '权限',
  `role` varchar(255) DEFAULT NULL COMMENT '角色',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into account (username, `password`, perms, role) values('ww', '123123', 'manage', 'administrator')

3. 自定义Realm

package com.example.realm;

import com.example.entity.Account;
import com.example.service.AccountService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author latin-xiao-mao
 * @date 2020/7/8 21:17
 * @description 在这里边定义我们自己的逻辑,必须要继承 AuthorizingRealm
 * 注意:写完 realm之后,我们必须要进行配置,才能起作用。我们配置在config包下面 ShiroConfig
 * @className AccountRealm
 */
public class AccountRealm extends AuthorizingRealm {


	@Autowired
	private AccountService accountService;

	/**
	 * 授权
	 * @param principalCollection
	 * @return
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		return null;
	}


	/**
	 * 认证
	 * @param authenticationToken
	 * @return
	 * @throws AuthenticationException
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

		// 首先我们需要获取 UsernamePasswordToken, shiro用来封装用户登录信息,使用用户的登录信息来创建令牌 Token
		// 注意这个客户端传过来的token中已经封装了用户的密码,用户名等信息
		UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

		// 从传过来的 token 中获取到用户名,然乎根据这个用户名去 查询数据库
		Account account = accountService.findByUsername(token.getUsername());

		// 判断account 用户名 是否存在
		if (account != null){
			// 若存在,我们就构造一个 SimpleAuthenticationInfo()有参对象返回,在这个对象中我们需要验证密码是否正确
			// 判断数据库中查出来的密码是否与 token 中带过来的密码是否相同。这里我们只需要把数据库查出来的密码传给它即可,
			// shiro 会自动将这个密码与 token 中携带的密码进行比对的
			// 第一个参数:是说明你要查找的是哪一个帐号
			// 第二个参数:是你数据库中查出来的真实密码
			// 第三个参数:是固定的name
			return new SimpleAuthenticationInfo(account, account.getPassword(), getName());
		}
		return null; // 用户名不存在,shiro则会自动抛出一个 UnknownAccountException。。异常的
	}
}

4.配置类 ShiroConfig

package com.example.config;

import com.example.realm.AccountRealm;
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;

/**
 * @author latin-xiao-mao
 * @date 2020/7/8 21:48
 * @description 在这里我们需要配置  3 个 bean :realm,DefaultWebSecurityManager,ShiroFilterFactoryBean
 * @className ShiroConfig
 */
@Configuration
public class ShiroConfig {

	/**
	 * ********************注意下面的注入 顺序 ******************
	 */


	/**
	 * 最后 将 DefaultWebSecurityManager 注入到 ShiroFilterFactoryBean 中
	 * 通过这三个方法的 bean,最后将这三者都 纳入到 IOC 的管理中了
	 * @return
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){

		// 这里也是同 下面一样,通过 方法名来获取 DefaultWebSecurityManager,从而将其注入到 ShiroFilterFactoryBean 中
		ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
		factoryBean.setSecurityManager(defaultWebSecurityManager);
		return factoryBean;
	}


	/**
	 * 再 将 Realm 注入到 DefaultWebSecurityManager 中
	 * @return
	 */
	@Bean
	public DefaultWebSecurityManager securityManager(@Qualifier("accountRealm") AccountRealm accountRealm){

		DefaultWebSecurityManager manager = new DefaultWebSecurityManager();

		// 我们现在需要将 下面的 realm 注入到 manager 中
		// 那么怎么注入呢?
		// 其实执行的时候,是先注入 下面的 realm 到 ioc 中,因此我们只需要从 ioc 中获取这个 realm 即可
		// 怎么从 ioc 中获取呢?(要知道realm注入IOC的时候其实默认是按照方法名注入的),因此我们根据方法名即可获取
		// 因此给 defaultWebSecurityManager 方法添加一个参数即可

		// 然后再将这个 realm 注入到 manager 中
		manager.setRealm(accountRealm);

		// 最后将 manager 返回即可
		return manager;
	}


	/**
	 * 先将我们刚才自定义的 realm,注入到 Spring 的 IOC 中,使其纳入ioc管理并生效
	 * @return
	 */
	@Bean
	public AccountRealm accountRealm(){

		return new AccountRealm();
	}
}

5.编写认证和授权规则

认证过滤器:

  • anon:无需认证
  • authc:必须认证
  • authcBasic:需要通过 HTTPBasic 认证
  • user:不一定通过认证,只要曾经被Shiro记录即可,比如:记住我的功能

授权过滤器:

  • perms:必须拥有某个权限才能访问
  • role:必须拥有某个角色才能访问
  • port:请求的端口必须是指定值才可以
  • rest:请求必须基于RESTFul,POST、PUT、GET、DELETE
  • ssl:必须是安全的 URL 请求,协议是 HTTPS

创建3个页面:main.html manage.html administrator.html 访问权限如下:

  1. 必须登录才能访问 main.html
  2. 当前用户必须拥有manage授权才能访问manage.html
  3. 当前用户必须拥有administrator角色才能访问administrator.html