Security is everywhere. I took advantage of the holiday to read Shiro's documents and document Shiro's integration of Spring Boot to control access rights based on roles in the database
Introduction
Apache Shiro is a powerful, flexible, open source security framework. It handles authentication, authorization, enterprise session management and encryption cleanly.
The above picture shows the basic architecture of Shiro
Authentication
Sometimes called "login" to prove that the user is the user themselves
Authorization
The process of access control, that is, determine "who" accesses "what"
Session Management
Manage user-specific sessions. In Shiro, you can find that all user session information will be controlled by Shiro.
Cryptography (encryption)
Encryption algorithms on data sources while ensuring ease of use
Start
environment
Spring Boot 1.5.9 MySQL 5.7 Maven 3.5.2 Spring Data Jpa Lombok
Add dependencies
Only the main Shiro dependencies are given here
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.4.0-RC2</version> </dependency>
Configuration
We only need the user table and role table for the time being. Modifying the configuration file in Spring boot will automatically create a database table for us
server: port: 8888spring: datasource: driver-class-name: com.mysql.jdbc.Driver username: root password: root url: jdbc:mysql://localhost:3306/shiro?characterEncoding=utf-8&useSSL=false jpa: generate-ddl: true hibernate: ddl-auto: update show-sql: true
entity
Role.java
@Data@Entitypublic class Role { @Id @GeneratedValue private Integer id; private Long userId; private String role;}User.java
@Data@Entitypublic class User { @Id @GeneratedValue private Long id; private String username; private String password;}Realm
First, create the Realm class, inherit from AuthorizingRealm, and customize our own authorization and authentication methods. Realm is a component that can access security data specific to the application, such as users, roles, and permissions.
Realm.java
public class Realm extends AuthorizingRealm { @Autowired private UserService userService; //Authorize @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //Get username from credentials String username = (String) SecurityUtils.getSubject().getPrincipal(); //Query user object based on username User user = userService.getUserByUserName(username); //Query the roles owned by the user List<Role> list = roleService.findByUserId(user.getId()); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Role role : list) { //Give the user role info.addStringPermission(role.getRole()); } return info; } //Authorize @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //Get the username of the current user String username = (String) authenticationToken.getPrincipal(); //Finding user from the database User user = userService.getUserByUserName(username); if (userService.getUserByUserName(username) == null) { throw new UnknownAccountException( "The corresponding user information was not found in this system."); } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName()); return info; }}Shiro configuration class
ShiroConfig.java
@Configurationpublic class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); //The following is the filter chain, filtering in order, so /** needs to put the last static resource //open filterChainDefinitionMap.put("/favicon.ico", "anon"); //Web icon filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; }@Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(myRealm()); return defaultWebSecurityManager; } @Bean public MyRealm myRealm() { MyRealm myRealm = new MyRealm(); return myRealm; }}Controller
UserController.java
@Controllerpublic class UserController { @Autowired private UserService userService; @GetMapping("/") public String index() { return "index"; } @GetMapping("/login") public String toLogin() { return "login"; } @GetMapping("/admin") public String admin() { return "admin"; } @PostMapping("/login") public String doLogin(String username, String password) { UsernamePasswordToken token = new UsernamePasswordToken(username, password); Subject subject = SecurityUtils.getSubject(); try { subject.login(token); } catch (Exception e) { e.printStackTrace(); } return "redirect:admin"; } @GetMapping("/home") public String home() { Subject subject = SecurityUtils.getSubject(); try { subject.checkPermission("admin"); } catch (UnauthorizedException exception) { System.out.println("No sufficient permissions"); } return "home"; } @GetMapping("/logout") public String logout() { return "index"; }}Service
UserService.java
@Servicepublic class UserService { @Autowired private UserDao userDao; public User getUserByUserName(String username) { return userDao.findByUsername(username); } @RequiresRoles("admin") public void send() { System.out.println("I now have the role admin, and can execute this statement"); }}Display layer
admin.html
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><html lang="en"/><head> <meta charset="UTF-8"/> <title>Title</title></head><body><form action="/login" method="post"> <input type="text" name="username" /> <input type="password" name="password" /> <input type="submit" value="Login" /></form></body></html>
home.html
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><html lang="en"/><head> <meta charset="UTF-8"/> <title>Title</title></head><body>home</body></html>
index.html
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><html lang="en"/><head> <meta charset="UTF-8"/> <title>Title</title></head><body>index<a href="/login" rel="external nofollow" >Please log in</a></body></html>
login.html
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><html lang="en"/><head> <meta charset="UTF-8"/> <title>Title</title></head><body><form action="/login" method="post"> <input type="text" name="username" /> <input type="password" name="password" /> <input type="submit" value="Login" /></form></body></html>
Summarize
This small case implements the control of user access based on roles, the most important of which is Realm, which acts as a "bridge" or "connector" between Shiro and application security data.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.