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 访问权限如下:
- 必须登录才能访问 main.html
- 当前用户必须拥有manage授权才能访问manage.html
- 当前用户必须拥有administrator角色才能访问administrator.html