Overview of shiro
- Apache Shiro is a security framework for Java
- Shiro is a powerful and easy-to-use Java security framework, mainly used for more convenient authentication, authorization, encryption, session management, integration with the Web, caching, etc.
- Shiro is small and simple to use
- There is spring security in spring, which is a permissions framework. It depends too closely on spring and is not easy to use without shiro.
- shiro does not depend on spring, shiro can not only implement permission management for web applications, but also implement c / s system, distributed system permission management,
- Shiro is a lightweight framework, and more and more enterprise projects are using Shiro.
Shiro core concepts
- Authentication: Identity authentication / login to verify whether the user has the corresponding identity;
- Authorization: Authorization, that is, authorization verification, to verify whether an authenticated user has a certain authorization;
- Session Manager: Session management, that is, a session after a user logs in. Before logging out, all its information is in the session;
- Cryptography: encryption to protect the security of data
- Web Support: Web support, can be easily integrated into the Web environment;
- Caching: Caching, for example, after a user logs in, their user information and roles / permissions do not have to be checked every time, which can improve efficiency;
- Concurrency: Shiro supports concurrent verification of multi-threaded applications, that is, if another thread is started in one thread, the permissions can be automatically propagated;
- Testing: Provide testing support;
- Run As: Allow one user to pretend to be another user (if they allow) to access;
- Remember Me: Remember me, this is a very common function, that is, after logging in once, you don't need to log in if you come back next time.
Main concepts
1. Subject current user
- It can be something that human crawlers currently interact with the software
- In shiro, we can collectively refer to "users" anywhere in the code, you can easily get Shiro Subject.
- Once you get the Subject, you can immediately get 90% of what you want to do with Shiro for the current user, log in, log out, access the session, perform authorization checks, etc.
2. SecurityManager
- SecurityManager manages the security operations of all users
- Reference to multiple internal nested security components, which is the core of the Shiro framework
- You can think of it as the DispatcherServlet front controller.
- Used to schedule various Shiro framework services
3. Realms
- Realms is the user's information authenticator and the user's authority authenticator
- When performing authentication (login) and authorization (access control), Shiro will find a lot of content from the Realm of the application configuration
- Realm can be understood as a DAO that reads user information, roles and permissions
- SecurityManager wants to verify the user's identity and permissions, then it needs to obtain the corresponding information from Realm for comparison to determine whether the user's identity is legal
- Realm can be regarded as a DataSource, that is, a secure data source.
4. Shiro architecture
- subject: The subject can be a user or a program. To access the system, the system needs to authenticate and authorize the subject.
- authenticator: The authenticator body performs authentication finally through the authenticator.
- authorizer: Authorization of the main body of the authorizer is finally carried out through the authenticator.
- sessionManager: Session management web applications generally use web containers to manage sessions. Shiro also provides a set of session management methods.
- sessionDao: manage session data through sessionDao,
- cacheManager: The cache manager mainly caches session and authorization data, such as managing the authorization data through cacheManager and integrating with ehcache to manage the cached data.
- realm: The realm is equivalent to a data source, and access to authentication and authorization related data through realm.
- cryptography: Password management provides a set of encryption / decryption components for easy development. For example, provide commonly used hash, encryption / decryption and other functions.
Springboot matching shiro
-
Create a new springboot project
-
Import springboot-web dependencies
-
To write controller and front-end login page, you
need to integrate thymeleaf to join thymeleaf's dependencies
<!--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. Write the front-end page
Write login.html, add.html, delete.html, index.html in the templates directory to
import dtd of thymeleaf
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. Write a controller to jump to the login page
@RequestMapping({"/","tologin"})
public String tologin(){
return "login";
}
- Run the startup browser and enter localhost: 8080
- Import springboot to integrate shiro and mybatis to connect to the database
<!--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>
- Create a database for the next authentication and authorization
##配置数据驱动信息 (key固定)
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql:///spring_shiro
spring.datasource.username = root
spring.datasource.password =123456
Add database information in application.properties
- Write mapper, service, pojo
pojo:
mapper:
service:
Impl:
controller: test whether it can be queried
- Write shiroconfig configuration class
- Write realm class to inherit AuthorizingRealm class and implement methods
- Write code in 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();
}
}
- Write code in 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. Rewrite the controller
@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";
}
- Write an unauthorized page
Unauthorized.html
- run:
The root user only has user: delete permissions, so you can only see the delete button. The
dj user has only user: add permissions, and you can only see the
ss user.
There are also encryption methods such as md5, which can be added by yourself and will not be introduced one by one.
Focus: shiroConfig class and UserRealm class configure the core **