Shrio
页面报错
<link rel="shortcut icon" href="#"/>
简单的安全框架
是一款java的主流的java的安全框架,它不依赖于任何容器,可以运行在javaEE和javaSE中,它的主要作用是对访问系统的用户进行身份认证,授权,会话管理,加密操作。
Shrio是用来解决安全管理的系统化的框架
Shrio的核心组件
用户,角色,权限
- 角色赋予权限
- 用户赋予角色
UsernamePasswordToken
Shrio用来封装用户的登录信息,使用户的登录信息来创建一个令牌Token
SecurityManager
Shrio的核心部分,负责安全认证和授权。
Subject
Shrio的抽象概念,包含了用户信息
Realm *
开发者自定义的模块,根据项目的需求,验证和授权的逻辑全部写在Realm里面
AuthenticatInfo
用户的角色信息集合,认证时使用
AuthorzationInfo
角色的权限信息集合,授权时使用
DefaultWebSecurityMannager
安全管理器,开发者自定义的Realm需要注入DefaultWebSecurityMannager才能生效
ShiroFilterFactoryBean
过滤器工厂,Shiro的基本运行机制是开发者定义的规则,Shiro去执行,具体的执行操作就是ShiroFilterFactoryBean创建的一个个Fillter对象来完成的
整合shrio使用SpringBoot
1.pom导入依赖:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.southwind</groupId>
<artifactId>shrio</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shrio</name>
<description>Demo project for Spring Boot</description>
<properties>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
<!-- mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
构建工程mvn clean install
2.自定义shrio过滤器
a.持久层
mybatis plus
package com.southwind.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.southwind.entity.Account;
import org.springframework.stereotype.Repository;
@Repository
public interface AccountMapper extends BaseMapper<Account> {
}
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/text
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
b.服务层
接口:
package com.southwind.service;
import com.southwind.entity.Account;
public interface AccountService {
public Account findByUsername(String name);
}
实现类:
package com.southwind.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.southwind.entity.Account;
import com.southwind.mapper.AccountMapper;
import com.southwind.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountMapper accountMapper;
@Override
public Account findByUsername(String name) {
QueryWrapper wrapper = new QueryWrapper();
wrapper.eq("username",name);
return accountMapper.selectOne(wrapper);
}
}
c.编写realm
package com.southwind.realm;
import com.southwind.entity.Account;
import com.southwind.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;
public class AccountRealm extends AuthorizingRealm {
@Autowired
private AccountService accountService;
/**
* 用户的角色信息 2.授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
/**
* 用户的权限信息 1.认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token =(UsernamePasswordToken) authenticationToken;
//获得用户信息 依据用户名去数据库查询
Account account =accountService.findByUsername(token.getUsername());
if(account!=null){
// 返回验证密码,丢进去参数会自己进行比较--然后捕获抛出的异常
return new SimpleAuthenticationInfo(account,account.getPassword(),getName());
}
return null;
}
}
d.注入realm编写配置类
package com.southwind.config;
import com.southwind.entity.Account;
import com.southwind.realm.AccountRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class config {
// 注入工厂
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("SecurityManager")DefaultWebSecurityManager manager){
ShiroFilterFactoryBean factoryBean =new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(manager);
return factoryBean;
}
@Bean
public DefaultWebSecurityManager SecurityManager(@Qualifier("accountRealm") AccountRealm accountRealm){
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(accountRealm);
return manager;
}
@Bean
public AccountRealm accountRealm(){
return new AccountRealm();
}
}
c.编写认证和授权规则
认证过滤器
- anon:无需认证
- authc:必需认证
- authcBasic:需要通过HTTPBasic认证
- user:不一定通过认证,只要曾经被Shiro记录即可,比如记住我
授权过滤器
- perms:必须拥有摸个权限才能访问
- role:必须有某个角色才能访问
- port:请求的端口必须是指定值才可以
- rest:请求必学基于RESTful,PUT POST GET DELETE
- ssl:必须是安全的URL请求,协议HTTPS
思路
-
创建3个页面,main.html manage.html administator.html
访问如下:
- 必须登录才能访问main.html
- 当前用户必学拥有manage授权才能访问manage.html
- 当前用户必须拥有administator角色才能访问administator.html
3.具体细节:
a.在config配置类中添加
package com.southwind.config;
import com.southwind.entity.Account;
import com.southwind.realm.AccountRealm;
import org.apache.commons.collections.map.HashedMap;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class config {
// 注入工厂
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("SecurityManager")DefaultWebSecurityManager manager){
ShiroFilterFactoryBean factoryBean =new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(manager);
// 权限设置
Map<String,String> map = new HashMap<>();
map.put("/main","authc");
map.put("/manage","perms[manage]");
map.put("/administator","roles[administator]");
factoryBean.setFilterChainDefinitionMap(map);
return factoryBean;
}
@Bean
public DefaultWebSecurityManager SecurityManager(@Qualifier("accountRealm") AccountRealm accountRealm){
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(accountRealm);
return manager;
}
@Bean
public AccountRealm accountRealm(){
return new AccountRealm();
}
}
b.添加controller
package com.southwind.controller;
import com.southwind.entity.Account;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class AccountHandler {
@GetMapping("/{url}")
public String index(@PathVariable("url") String url){
return url;
}
@PostMapping("/login")
public String login(String username, String password, Model model){
Subject subject= SecurityUtils.getSubject();
UsernamePasswordToken token =new UsernamePasswordToken(username,password);
try {
subject.login(token);
com.southwind.entity.Account account=(Account)subject.getPrincipal();
subject.getSession().setAttribute("account",account);
return "index";
}catch (UnknownAccountException e){
e.printStackTrace();
model.addAttribute("msg","用户名错误");
return "login";
}catch (IncorrectCredentialsException e){
e.printStackTrace();
model.addAttribute("msg","密码错误");
return "login";
}
}
@GetMapping("/unauth")
@ResponseBody
public String unauth(){
return "未授权,无法访问";
}
@GetMapping("/logout")
public String logout(){
Subject subject= SecurityUtils.getSubject();
subject.logout();
return "login";
}
}
c.配置视图解析器
创建index:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>index</h1>
<div th:if="${session.account !=null}">
<span th:text="${session.account.username}+'欢迎回来'"></span><br>
<a href="/logout">退出</a>
<a href="/main">mian</a>|<a href="/manage">manage</a>|<a href="/administrator">administrator</a>
</div>
</body>
</html>
创建main:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="shortcut icon" href="#"/>
</head>
<body>
<h1>首页</h1>
</body>
</html>
创建manage:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="shortcut icon" href="#"/>
</head>
<body>
<h1>manage</h1>
</body>
</html>
创建administrator
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="shortcut icon" href="#"/>
</head>
<body>
<h1>administrator</h1>
</body>
</html>
创建login:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="shortcut icon" href="#"/>
</head>
<body>
<form action="/login" method="post">
<table>
<span th:text="${msg}"></span>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
浙公网安备 33010602011771号