Visão geral do shiro
- Apache Shiro é uma estrutura de segurança para Java
- O Shiro é uma estrutura de segurança Java poderosa e fácil de usar, usada principalmente para autenticação, autorização, criptografia, gerenciamento de sessões mais convenientes, integração com a Web, cache, etc.
- Shiro é pequeno e simples de usar
- Há segurança na primavera, que é uma estrutura de permissões, que depende muito da primavera e não é fácil de usar sem o shiro.
- O shiro não depende da primavera, o shiro não pode apenas implementar o gerenciamento de permissões para aplicativos da web, mas também implementar o sistema c / s, gerenciamento distribuído de permissões do sistema,
- Shiro é uma estrutura leve, e mais e mais projetos corporativos estão usando Shiro.
Conceitos principais do Shiro
- Autenticação: autenticação de autenticação / login para verificar se o usuário tem a identidade correspondente;
- Autorização: autorização, ou seja, verificação de autorização, para verificar se um usuário autenticado possui uma certa autorização;
- Gerenciador de sessões: gerenciamento de sessões, ou seja, uma sessão após o usuário efetuar login. Antes de efetuar logout, todas as informações estão na sessão;
- Criptografia: criptografia para proteger a segurança dos dados
- Suporte da Web: O suporte da Web pode ser facilmente integrado ao ambiente da Web;
- Armazenamento em cache: em cache, por exemplo, depois que um usuário faz login, suas informações e funções / permissões de usuário não precisam ser verificadas todas as vezes, o que pode melhorar a eficiência;
- Simultaneidade: o Shiro suporta a verificação simultânea de aplicativos multithread, ou seja, se outro thread for iniciado em um thread, as permissões poderão ser propagadas automaticamente;
- Teste: Forneça suporte para teste;
- Executar como: permite que um usuário finja ser outro usuário (se permitir) para acessar;
- Lembre-se de mim: lembre-se de mim, essa é uma função muito comum, ou seja, depois de fazer o login uma vez, você não precisa fazer login se voltar na próxima vez.
Principais conceitos
1. Assunto usuário atual
- Pode ser algo que os rastreadores humanos interagem atualmente com o software
- No shiro, podemos nos referir coletivamente a "usuários" em qualquer lugar do código, você pode facilmente obter o Shiro Subject.
- Depois de obter o Assunto, você pode obter imediatamente 90% do que deseja fazer com o Shiro para o usuário atual, efetuar login, sair, acessar a sessão, executar verificações de autorização etc.
2. SecurityManager
- SecurityManager gerencia as operações de segurança de todos os usuários
- Referência a vários componentes de segurança internos aninhados, que é o núcleo da estrutura Shiro
- Você pode pensar nisso como o controlador frontal do DispatcherServlet.
- Usado para agendar vários serviços de estrutura Shiro
3. Reinos
- Realms é o autenticador de informações do usuário e o autenticador de autoridade do usuário
- Ao executar autenticação (login) e autorização (controle de acesso), o Shiro encontrará muito conteúdo no Domínio da configuração do aplicativo
- Região pode ser entendida como um DAO que lê informações, funções e permissões do usuário
- O SecurityManager deseja verificar a identidade e as permissões do usuário e precisa obter as informações correspondentes do Realm para comparação para determinar se a identidade do usuário é legal;
- O território pode ser considerado como uma fonte de dados, ou seja, uma fonte de dados segura.
4. arquitetura Shiro
- assunto: o assunto pode ser um usuário ou um programa.Para acessar o sistema, o sistema precisa autenticar e autorizar o assunto.
- autenticador: o corpo do autenticador efetua a autenticação finalmente através do autenticador.
- autorizador: A autorização do corpo principal do autorizador é finalmente realizada através do autenticador.
- sessionManager: Os aplicativos Web de gerenciamento de sessões geralmente usam contêineres da Web para gerenciar sessões.O Shiro também fornece um conjunto de métodos de gerenciamento de sessões.
- sessionDao: gerenciar dados da sessão através do sessionDao,
- cacheManager: o gerenciador de cache armazena em cache principalmente os dados da sessão e da autorização, como o gerenciamento dos dados de autorização por meio do cacheManager e a integração com o ehcache para gerenciar os dados em cache.
- região: a região é equivalente a uma fonte de dados e acesso a dados relacionados à autenticação e autorização por meio da região.
- criptografia: o gerenciamento de senhas fornece um conjunto de componentes de criptografia / descriptografia para facilitar o desenvolvimento. Por exemplo, forneça hash, criptografia / descriptografia comumente usados e outras funções.
Shiro de correspondência Springboot
-
Crie um novo projeto springboot
-
Importar dependências do springboot-web
-
Para escrever a página de login do controlador e do front-end, você
precisa integrar o thymeleaf para ingressar nas dependências do thymeleaf
<!--thymeleaf依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
4. Escreva a página inicial
Escreva login.html, add.html, delete.html, index.html no diretório de modelos para
importar o dtd do timeleaf
xmlns:th="http://www.thymeleaf.org"
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<form th:action="login">
<input type="text" name="username" value="">
<input type="password" name="password" value="">
<input type="submit" value="登录">
</form>
</body>
</html>
index.html
add.html
delete.html
5. Escreva um controlador para ir para a página de login
@RequestMapping({"/","tologin"})
public String tologin(){
return "login";
}
- Execute o navegador de inicialização e insira localhost: 8080
- Importe springboot para integrar shiro e mybatis para conectar-se ao banco de dados
<!--shiro-整合spring的包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.2</version>
</dependency>
<!--shiro整合thymeleaf-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
- Crie um banco de dados para a próxima autenticação e autorização
##配置数据驱动信息 (key固定)
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql:///spring_shiro
spring.datasource.username = root
spring.datasource.password =123456
Inclua informações do banco de dados em application.properties
- Escreva mapper, service, pojo
pojo:
mapper:
service:
Impl:
controller: teste se ele pode ser consultado
- Gravar classe de configuração shiroconfig
- Grave a classe de região para herdar a classe AuthorizingRealm e implemente métodos
- Escreva código no shiroConfig
@Configuration
public class shiroConfig {
//3. shiroFilterfactaryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);//设置安全管理器
shiroFilterFactoryBean.setLoginUrl("/toLogin");//没有认证后跳到的页面
/**
* shiro的内置过滤器
anon:无需认证就可以访问 默认
authc:必须认证了才能访问
user:必须拥有记住我功能才能访问
perms:必须拥有对某个的权限才能访问
role:拥有某个角色权限才能访问
*/
//添加shiro的内置过滤器 设置要拦截的url
Map<String,String> filterChainDefinitionMap=new LinkedHashMap<>();//拦截
filterChainDefinitionMap.put("/add","authc");// /add请求必须认证才能访问
filterChainDefinitionMap.put("/del","authc");//del必须认证才能访问
// filterChainDefinitionMap.put("user/**","authc");//支持通配符
//授权
filterChainDefinitionMap.put("/add","perms[user:add]");//没有这个user:add权限的会被拦截下来
filterChainDefinitionMap.put("/del","perms[user:delete]");//没有这个user:delete权限的会被拦截下来
//未授权的跳转的url
shiroFilterFactoryBean.setUnauthorizedUrl("/Unauthorized");
//设置注销的url
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//把设置好的过滤设置到ShiroFilterFactoryBean
return shiroFilterFactoryBean;
}
//2. DefaultWebSecurityManager
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联realm对象 userRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//1. 创建realm对象 自定义的·类
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
//整合shiroDialect:用来整合shiro-thymeleaf
@Bean
public ShiroDialect getshiroDialect(){
return new ShiroDialect();
}
}
- Escreva código no UserRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
InfoService service;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权 doGetAuthorizationInfo");
SimpleAuthorizationInfo simpInfo = new SimpleAuthorizationInfo();
//获取当前用户的对象
Subject subject=SecurityUtils.getSubject();
Info user = (Info)subject.getPrincipal();//获取用户信息
simpInfo.addStringPermission(user.getPerm());//获取数据库权限
return simpInfo;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证 doGetAuthorizationInfo");
//获取当前的用户
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken userToken=(UsernamePasswordToken)authenticationToken;//获取登录的信息
//获取用户名 密码 数据库取
System.out.println(userToken.getUsername());
Info query = service.queryByName(userToken.getUsername());
System.out.println(query);
if(query==null){//没有这个用户
return null;
}
Session session=subject.getSession();//获取用户的session
session.setAttribute("loginuser",query);
if(!userToken.getUsername().equals(query.getUsername())){//判断登录的用户名密码 匹配数据库是否正确
return null;//抛出异常
}
//密码认证,shiro做
return new SimpleAuthenticationInfo(query,query.getPassword(),"");
}
}
14. Reescreva o controlador
@RequestMapping("/login")
public String login(String username,String password){
try {
//获取当前的用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登录数据
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
subject.login(usernamePasswordToken);//执行登录的方法 没有异常就成功了
return "index";
} catch (UnknownAccountException e) {
/**
* 异常信息
* UnknownAccountException :用户名不存在
* IncorrectCredentialsException:密码错误
*/
e.printStackTrace();
System.out.println("用户名不存在");
}catch (IncorrectCredentialsException e){
System.out.println("密码错误");
}
return "login";
}
@RequestMapping("/add")
public String add(){//跳转页面
return "add";
}
@RequestMapping("/del")
public String delete(){//跳转页面
return "delete";
}
@RequestMapping("/Unauthorized")
public String Unauthorized(){//没有权限跳转的url
return "Unauthorized";
}
//注销
@RequestMapping("/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
session.setAttribute("loginuser",null);//清空session
return "login";
}
- Escreva uma página
não autorizada Unauthorized.html
- Execute:
O usuário root possui apenas permissões user: delete, para que você possa ver apenas o botão
delete.O usuário dj possui apenas user: add permissões e você pode ver apenas o
usuário add ss. Nenhuma permissão, portanto, nenhum botão é visível.
Também existem métodos de criptografia, como o md5, que podem ser adicionados por você e não serão introduzidos um por um.
Foco: a classe shiroConfig e a classe UserRealm configuram o núcleo **