什么是Shiro?Shiro是一款主流的Java安全框架,它不依赖任何容器,可以运行在JavaSE还有JavaEE项目中,它的主要作用是对访问系统的用户进行身份认证、授权、会话管理、加密等操作。
在Shiro中 有角色(role)、权限(perms)
会给角色赋予权限,在给用户赋予角色
1、UsernamePasswordToken:Shiro用来封装用户的登录信息,使用用户的登录信息来创建Token。
2、SecurityManager:Shiro的抽象部分,负责安全认证和授权。
3、Subject:Shiro的一个抽象概念,包含了用户信息。
4、Realm:开发者定义的模块,可以根据项目的需求在里面开发所需要的验证和授权的逻辑全部都写在Realm中。
5、AuthenticationInfo:用户的角色信息集合,认证的时候使用。
6、AuthorizationInfo:角色的权限信息集合,授权时使用。
7、DefaultWebSecurityManager:安全管理器,开发者自定义的Realm要注入到DefaultWebSecurityManager进行管理才能生效。
8、ShiroFilterFactoryBean:过滤器工厂,Shiro的运行规则是由开发者来自定义的,Shiro去创建一个个对应的Filter来进行实现。
1、通过IDEA创建Spring Boot的Maven工程,并在POM.XML来进行依赖导入。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion>
<groupId>org.junit.vintagegroupId>
<artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.5.3version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.3.1.tmpversion>
dependency>
2、编写自定义Realm(认证规则,授权规则在这里写)
//这里继承了一个AuthorizingRealm类并实现里面的抽象方法
public class AccountRealm extends AuthorizingRealm {
//AccountService中只写了一个通过用户名查找用户的方法。
@Autowired
private AccountService accountService;
/**
* @Description:授权的方法
* @Param: [principalCollection]:
* @return: org.apache.shiro.authz.AuthorizationInfo:
* @Author: litao
* @Date: 2020/7/6 14:51
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //AuthorizationInfo的实现类
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//获取当前认证成功的accouunt用户 可以通过Subject来获取或者通过principalCollection来获取。
Account account = (Account) principalCollection.getPrimaryPrincipal();
//赋予身份
authorizationInfo.addRole(account.getRole());
//赋予权限
authorizationInfo.addStringPermission(account.getPerms());
return authorizationInfo;
}
/**
* @Description:认证的方法
* @Param: [authenticationToken]:
* @return: org.apache.shiro.authc.AuthenticationInfo:
* @Author: litao
* @Date: 2020/7/6 14:51
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//通过用户名查找用户。
Account account = accountService.findAccountByUsername(token.getUsername());
if (account != null) {
//不为空的时候返回一个 Authentication的实现类。
//SimpleAuthenticationInfo的构造器有三个参数第一个是通过数据库查找出来的account,第二个是 它的密码,第三个是当前Realm的名字。
return new SimpleAuthenticationInfo(account, account.getPassword(), this.getName());
}
return null;
}
}
3、编写Shiro的配置类并向IOC容器注入
@Configuration
public class ShiroConfig {
@Bean
//向IOC容器注入ShiroFilterFactoryBean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager manager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(manager);
//认证和权限规则
Map<String, String> map = new HashMap<>();
//设置main请求必须是认证的用户才能访问
map.put("/main", "authc");
//设置manage的请求是拥有mange权限的才能访问
map.put("/manage", "perms[manage]");
//设置administrator的请求是拥有administrator角色的用户才能访问
map.put("/administrator", "roles[administrator]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
//设置登录页面
shiroFilterFactoryBean.setLoginUrl("/login");
//设置未经授权页面
shiroFilterFactoryBean.setUnauthorizedUrl("/autho");
return shiroFilterFactoryBean;
}
@Bean
//向IOC容器注入DefaultWebSecurityManager
public DefaultWebSecurityManager securityManager(@Qualifier("accountRealm") AccountRealm accountRealm) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(accountRealm);
return manager;
}
@Bean
//向IOC容器注入AccountRealm
public AccountRealm accountRealm() {
return new AccountRealm();
}
}
编写Realm的认证和授权规则有以下规则
认证过滤器
anon:无需认证
authc:必须认真才能访问
authcBasic:需要通过HTTPBasic认证。
user:不一定需要认真,只要被Shiro曾经记录过即可有点像记住密码。
授权过滤器
perms:必须拥有某个权限才能访问。
role:必须拥有某个角色才能访问。
port:请求端口必须是指定值才能访问。
rest:请求必须是RESTful、POST、PUT 、GET、DELETE。
ssl:必须是安全的URL请求,协议Https。
4、Controller
@Controller
public class AccountController {
//Templater
@GetMapping("/{url}")
public String url(@PathVariable("url") String url) {
return url;
}
//登录方法
@PostMapping("/login")
public String login(String username, String password) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
return "index";
} catch (UnknownAccountException e) {
e.printStackTrace();
return "login";
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
return "login";
}
}
//未授权的访问请求
@GetMapping("/autho")
@ResponseBody
public String author() {
return "未经授权";
}
}