Shiro
Shiro profile
Shiro is what?
- Apache Shiro is a Java
Security (permissions) framework
. - Shiro can easily develop applications that are good enough to be used in both JavaSE and JavaEE environments.
- Shiro can do it,
certification
.authorization
.encryption
.Session management
.Web integration
.The cache
And so on. - Liverpoolfc.tv: shiro.apache.org/
- Official documentation 10 minutes quick Start: shiro.apache.org/10-minute-t…
- Download :github.com/apache/shir…
Shiro’s three main functions
Shiro has three core components, Subject, SecurityManager, and Realm
-
Subject: indicates the authentication Subject. The object with which the application code interacts directly is Subject, which represents the current user. The Principals and Credentials are included.
-
SecurityManager: indicates the security administrator. Is the core of Shiro’s architecture. All interactions with the Subject are delegated to the SecurityManager, the Subject is the facade, and the SecurityManager is the real performer. It is responsible for interacting with Shiro’s other components.
-
Realm: Is a Realm. Acts as a “bridge” between Shiro and application security data. Shiro obtains security data (such as users, roles, and permissions) from a Realm. To authenticate users, The SecurityManager needs to obtain the corresponding users from a Realm for comparison to determine whether they are legitimate. You need to obtain user roles and permissions from the Realm to verify that user operations can be performed. You can view the Realm as a DataSource.
Authentication
: identity authentication, login, verify whether the user has the corresponding identity;Authorization
: Authorization, namely, permission verification, verifies whether an authenticated user has a certain permission, that is, determines whether the user can perform operations, for example, verify whether a user has a role, or verify whether a user has a certain permission on a resource in a fine-grained manner.Session Manager
: Session management, that is, after the user logs in, it is the second session. All the information about it is in the session before the user logs out. The session can be a normal JavaSE environment or a Web environment;Cryptography
Encryption: Protects the security of data. For example, passwords are encrypted and stored in a database rather than in plain text.Web Support
: Web support, can be very easy integration into the Web environment;Caching
: Cache. For example, after a user logs in, the user information, roles, and permissions do not need to be checked every time, which improves efficiencyConcurrency
Shiro supports concurrent validation in multi-threaded applications, which means that permissions can be automatically propagated, for example by starting another thread in one threadTesting
: Provide test support;RunAs
Allow one user to pretend to be another user (if they allow it).Remember Me
: Remember me, this is a very common feature, which means that once you log in, you don’t need to log in the next time
Shiro Architecture (External)
Shiro from the outside, that is, from an application perspective, see how Shiro gets things done: Subject user, SecurityManager manages all user Realm connection data
-
subject: The object of direct interaction of application code is Subject, that is to say, Shiro’s external API core is Subject, Subject represents the current user, the user is not necessarily a specific person, anything interacting with the current application is Subject, such as web crawler, robot, etc. All interactions with the Subject are delegated to the SecurityManager; The Subject is a facade, and the SecurityManager is the actual performer.
-
SecurityManager: The security manager, that is, all security-related operations interact with SercurityManager, and it manages all subjects. As you can see, it is the core of Shiro and is responsible for interacting with Shiro’s other components. It corresponds to the role of SpringMVC’s DispatcherServlet
-
Realm: Shiro obtains security data from realms (such as users, roles, and permissions). The SecurityManager needs to authenticate users from realms to determine whether their identities are valid. We need to get the user’s role and permission from Realm to verify whether the user’s operation can be performed.
Shiro Architecture (internal)
Subject
: Any user who can interact with the application;Security Manager
: equivalent to SpringMVCDispatcherSerlet
; Shiro isThe heart
All concrete interactions pass throughSecurity Manager
It manages all subjects and is responsible for authentication, authorization, session, and cache management.Authenticator
: be responsible forSubject
Authentication, is – an extension point that can be customized for implementation; You can useAuthentication strategy
(Authentication Strategy), that is, under what circumstances is the user authenticated;Authorizer
: authorizer, that is, access controller, used to determine whether the principal has permission to perform the corresponding operation; It controls the user’s access to the application
Those functions of;
Realm
Can have – one or more realms, which can be thought of as secure entity data sources for obtaining secure entities, can be implemented using JDBC, can be implemented in memory, and so on, provided by the user; So all applications need to implement their own realmSessionManager
: a component that manages the Session lifecycle, and Shiro can be used not only in Web environments, but also in normal JavaSE environmentsCacheManager
: cache controller to manage caches such as users, roles, permissions, etc. Because this data rarely changes, caching can improve access performance;Cryptography
: Password module, Shiro enhances some common encryption components for password encryption, decryption, etc
Shiro Quick start
The preparatory work
Download: GitHub resource
Create a normal Maven project, Springboot-08-shiro, and delete the SRC directory and the useless files
Create a new SpringMVC project hello_shiro in Springboot-08-shiroFind the file pom.xmlGithub.com/apache/shir…
Copy dependencies in POM.xml
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</dependency>
<! -- configure logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
</dependency>
</dependencies>
Copy the code
Change add version number:
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
Copy the code
copyGithub.com/apache/shir… log4j.properties
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
# General Apache libraries
log4j.logger.org.apache=WARN
# Spring
log4j.logger.org.springframework=WARN
# Default Shiro logging
log4j.logger.org.apache.shiro=INFO
# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN
Copy the code
Download the plug-in and restart IDEA
shiro.ini
[users]
# user 'root' with password 'secret' and the 'admin' role
root = secret, admin
# user 'guest' with the password 'guest' and the 'guest' role
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!";) ), and role'president'
presidentskroob = 12345, president
# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
darkhelmet = ludicrousspeed, darklord, schwartz
# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz
# -----------------------------------------------------------------------------
# Roles with assigned permissions
#
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
# -----------------------------------------------------------------------------
[roles]
# 'admin' role has all permissions, indicated by the wildcard The '*'
admin = *
# The 'schwartz' role can do anything (*) with any lightsaber:
schwartz = lightsaber:*
# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
# license plate 'eagle5' (instance specific id)
goodguy = winnebago:drive:eagle5
Copy the code
Continue copying:Github.com/apache/shir… Quickstart.java
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Quickstart {
// Use log output
private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
public static void main(String[] args) {
DefaultSecurityManager securityManager = new DefaultSecurityManager();
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
securityManager.setRealm(iniRealm);
SecurityUtils.setSecurityManager(securityManager);
// Now that a simple Shiro environment is set up, let's see what you can do:
// Now that you have set up a simple Shiro environment, let's see what you can do:
// get the currently executing user:
// Get the currently executing user: getSubject
Subject currentUser = SecurityUtils.getSubject();
// Get Session from the current user
Session session = currentUser.getSession();
session.setAttribute("someKey"."aValue");
String value = (String) session.getAttribute("someKey");
if (value.equals("aValue")) {
log.info("Securit=>Session! [" + value + "]");
}
// If indicates whether the current user is authenticated
if(! currentUser.isAuthenticated()) {// If the authentication succeeds, get the account password and generate a Token
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr"."vespa");
// Set remember me
token.setRememberMe(true);
try {
// Login operation performed!
currentUser.login(token);
} catch (UnknownAccountException uae) { // Unknown account
log.info("There is no user with username of " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {// The password is not normal, then output
log.info("Password for account " + token.getPrincipal() + " was incorrect!");
} catch (LockedAccountException lae) {// The user is locked. For example, the account is locked after five failed attempts
log.info("The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
}
// ... catch more exceptions here (maybe custom ones specific to your application?
catch (AuthenticationException ae) {
//unexpected condition? error?}}// Get the verification code of the current user
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");
// Test roles, such as vip1, vip2
if (currentUser.hasRole("schwartz")) {
log.info("May the Schwartz be with you!");
} else {
log.info("Hello, mere mortal.");
}
// Check if there are any permissions, coarse-grained!
if (currentUser.isPermitted("lightsaber:wield")) {
log.info("You may use a lightsaber ring. Use it wisely.");
} else {
// If all options are not met, output
log.info("Sorry, lightsaber rings are for schwartz masters only.");
}
// Whether to have more advanced permissions, fine granularity!
if (currentUser.isPermitted("winnebago:drive:eagle5")) {
log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " +
"Here are the keys - have fun!");
} else {
log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}
/ / logout
currentUser.logout();
// End the system
System.exit(0); }}Copy the code
Start the test
SpringBoot integrates Shiro environment setup
1. Create a SpringBoot project
To create the SpringBoot project shiro-Springboot, select Web and Thymeleaf
2. Create index.html under Templates
<! DOCTYPEhtml>
<html lang="en" xmlns:th="https://www.thymeleaf.org"
xmlns:shiro="https://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Home page</h1>
<p th:text="${msg}"></p>
</body>
</html>
Copy the code
3. Create myController.java under the Controller package
@Controller
public class MyController {
@RequestMapping({"/","/index"})
public String index(Model model){
model.addAttribute("msg"."hello,Shiro");
return "index"; }}Copy the code
Start test:
4. Three functions, basic understanding
Subject: user SecurityManager: manages all user Realm: connection data
5. Import the JAR package
<! --shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.41.</version>
</dependency>
Copy the code
6. Write ShiroConfig and UserRealm
public class UserRealm extends AuthorizingRealm {
/ / authorization
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("Authorized doGetAuthorizationInfo performed =");
return null;
}
/ / certification
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("Executed =" Authenticated doGetAuthenticationInfo");
return null; }}Copy the code
@Controller
public class ShiroConfig {
// Three core elements:
//ShiroFilterFactoryBean
// Step 3:
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// Set the security manager
bean.setSecurityManager(defaultWebSecurityManager);
return bean;
}
//DafaultWebSecurityManager
// Step 2:
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
/ / associated UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
// Create a Realm object that requires a custom class
// Step 1:
@Bean
public UserRealm userRealm(a){
return newUserRealm(); }}Copy the code
7. Write HTML pages
Create the user directory in the Templates directory to write the HTML pages, add.html, update.html
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
</head>
<body>
<h1>add</h1>
</body>
</html>
Copy the code
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>update</title>
</head>
<body>
<h1>update</h1>
</body>
</html>
Copy the code
8. Modify MyController to add response request
@Controller
public class MyController {
@RequestMapping({"/","/index"})
public String index(Model model){
model.addAttribute("msg"."hello,Shiro");
return "index";
}
@RequestMapping("/user/add")
public String add( ){
return "user/add";
}
@RequestMapping("/user/update")
public String update( ){
return "user/update"; }}Copy the code
9. Modify the Index home page
<! DOCTYPE html> <html lang="en" xmlns:th="https://www.thymeleaf.org"
xmlns:shiro="https://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<meta charset="UTF-8"> < title > title < / title > < / head > < body > < h1 > home page < / h1 > < p th: text ="${msg}"></p>
<br/><hr>
<a th:href="@{/user/add}">add</a>
<a th:href="@{/user/update}">update</a>
</body>
</html>
Copy the code
10. Final test
Shiro implements login interception
1. Create a login page
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>The login</title>
</head>
<body>
<h1 align="center">The login</h1>
<hr>
<form action="">
<p align="center">User name:<input type="text" name="username"></p>
<p align="center">The secret code:<input type="text" name="password"></p>
<p align="center"><input type="submit"></p>
</form>
</body>
</html>
Copy the code
2. Add jump to MyController
@RequestMapping("/toLogin")
public String toLogin(a){
return "login";
}
Copy the code
Add Shiro’s built-in filters
Authc: Authc must be authenticated. User: Must have, remember me function, to access perms: You can access perms only when you have the permission on a resource role: you can access perms only when you have the permission on a role
@Controller
public class ShiroConfig {
// Three core elements:
//ShiroFilterFactoryBean
// Step 3:
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
// Set the security manager
bean.setSecurityManager(defaultWebSecurityManager);
Add Shiro's built-in filters
/* Anon: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC: authC
// Set login permission to block login
Map<String, String> filterMap = new LinkedHashMap<>();
//filterMap.put("/user/add", "authc");
//filterMap.put("/user/update", "authc");
filterMap.put("/user/*"."authc");
bean.setFilterChainDefinitionMap(filterMap);
// Set the login request
bean.setLoginUrl("/toLogin");
return bean;
}
//DafaultWebSecurityManager
// Create a Realm object that requires a custom class.Copy the code
4. Start test:
We can see it’s been intercepted!
Shiro implements user authentication
1. Write certifications
@RequestMapping("/login")
public String login(String username,String password,Model model){
// Get the current user
Subject subject = SecurityUtils.getSubject();
// Encapsulate user login data
// Encapsulate as a Token
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
// Verify the login, if there are no exceptions, it is successful
subject.login(token);
return "index";
}catch (UnknownAccountException e){// The user name does not exist
model.addAttribute("msg"."User name error");
return "login";
}catch (IncorrectCredentialsException e){
model.addAttribute("msg"."Password error");
return "login"; }}Copy the code
2. Add a redirect and error message to login
<p align="center" th:text="${msg}" style="color: red"></p>
<form th:action="@{/login}">
<p align="center">User name:<input type="text" name="username"></p>
<p align="center">The secret code:<input type="text" name="password"></p>
<p align="center"><input type="submit"></p>
</form>
Copy the code
3. Determine the authentication
/ / certification
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("Executed =" Authenticated doGetAuthenticationInfo");
// The user name is obtained from the password data
String name="qingfeng";
String password="123456";
// Create a token
UsernamePasswordToken usertoken = (UsernamePasswordToken) token;
// Determine the incoming data
if(! usertoken.getUsername().equals(name)){return null;// UnknownAccountException was thrown
}
// Password authentication, shiro does
return new SimpleAuthenticationInfo("",password,"");
}
Copy the code
4. Test:
Password mistakeUser name errorLogin successful
Shiro integration mybatis
1. Import the SQL JAR package
<! --MySQL--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.022.</version> </dependency> <! --log4j--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.217.</version> </dependency> <! --druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2. 5</version> </dependency> <! --mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.14.</version>
</dependency>
Copy the code
2. Write application. Yml
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/mybatis? useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UT C
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
#Spring Boot does not inject these property values by default, you need to bind them yourself
#druid Data source proprietary configuration
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
# Configure filters to monitor statistics interception, stat: monitor statistics, log4j: logging, wall: defend against SQL injection
# if allowed times wrong Java. Lang. ClassNotFoundException: org.. Apache log4j. Priority
# import log4j dependence can, Maven address: https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true; druid.stat.slowSqlMillis=500
mybatis:
type-aliases-package: com.cy.pojo
mapper-locations: classpath:mapper/*.xml
Copy the code
3. Write entity class User,
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
private String perms;
}
Copy the code
4. Write UserMapper interface
@RequestMapping
@Mapper// This annotation indicates that this is a Mybatis mapper class
public interface UserMapper {
User queryUserByName(String name);
}
Copy the code
5. Create UserMapper. XML
Create the mapper directory usermapper.xml under the resource package
UserMapper.xml
<! DOCTYPEmapper
PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cy.mapper.UserMapper">
<select id="queryUserList" resultType="User">
select * from user;
</select>
<select id="queryUserByName" resultType="User" parameterType="String">
select * from user where name=#{name}
</select>
</mapper>
Copy the code
6. The service layer
UserService interface
package com.cy.service;
import com.cy.pojo.User;
public interface UserService {
public User queryUserByName(String name);
}
Copy the code
UserServiceImpl
package com.cy.service;
import com.cy.mapper.UserMapper;
import com.cy.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService{
@Autowired
UserMapper userMapper;
@Override
public User queryUserByName(String name) {
returnuserMapper.queryUserByName(name); }}Copy the code
7. Test
Tested ShiroSpringbootApplicationTests
@SpringBootTest
class ShiroSpringbootApplicationTests {
@Autowired
UserServiceImpl userService;
@Test
void contextLoads(a) {
System.out.println(userService.queryUserByName("The wind")); }}Copy the code
8. Modify the previous user authentication
Connect to a real database for user authentication
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
/ / authorization
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("Authorized doGetAuthorizationInfo performed =");
return null;
}
/ / certification
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("Executed =" Authenticated doGetAuthenticationInfo");
// Create a token
UsernamePasswordToken usertoken = (UsernamePasswordToken) token;
// Connect to a real database
User user = userService.queryUserByName(usertoken.getUsername());
if(user==null) {// The account was not found
return null;
}
// You can use encrypted MD5, MD5 appearance level encryption
// Password authentication, shiro does
return new SimpleAuthenticationInfo("",user.getPwd(),""); }}Copy the code
Shiro requests authorization implementations
1. Configure authorization in ShiroConfig
// Set login permission to block login
Map<String, String> filterMap = new LinkedHashMap<>();
// Authorization, normally, the page without authorization will be redirected to the unauthorized page
filterMap.put("/user/add"."perms[user:add]");
filterMap.put("/user/update"."perms[user:update]");
filterMap.put("/user/*"."authc");
bean.setFilterChainDefinitionMap(filterMap);
// Set the login request
bean.setLoginUrl("/toLogin");
// Unauthorized page
bean.setUnauthorizedUrl("/noauth");
return bean;
Copy the code
2. Set up a blocking page
@ResponseBody
@RequestMapping("/noauth")
public String unauthorized(a){
return "This page cannot be accessed without authorization";
}
Copy the code
3. Start the test
4. Authorize the user
UserRealm.java
/ / authorization
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("Authorized doGetAuthorizationInfo performed =");
// Note the distinction between SimpleAuthenticationInfo and SimpleAuthorizationInfo
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// info.addStringPermission("user:add");
// Get the object currently logged in
Subject subject = SecurityUtils.getSubject();
// Cast to User
User currentUser = (User) subject.getPrincipal();// Get the User object
// Set the permissions of the current user
info.addStringPermission(currentUser.getPerms());
return info;
}
Copy the code
Testing: We can see that authorization was successful
However, we found a problem that all users in the database can access it freely, so we should assign permissions to the database
5. Add a column to the user table
Binding authority
Shiro integration Thymeleaf
1. Import the JAR package
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
Copy the code
- The code
Structure directory:
2. Configure the config
ShiroConfig
ShiroDialect: used to integrate Shiro Thymeleaf
@Bean
public ShiroDialect getShiroDialect(a){
return new ShiroDialect();
}
Copy the code
3. Modify the index. HTML
<! DOCTYPE html> <html lang="en" xmlns:th="https://www.thymeleaf.org"
xmlns:shiro="https://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 align="center"Word-wrap: break-word! Important; "> <div align="center" th:if="${session.loginUser==null}">
<a th:href="@{/toLogin}"< div style = "box-sizing: border-box! Important; word-wrap: break-word! Important;"center" th:text="${msg}"></p>
<br/><hr>
<div align="center" Shiro:hasPermission="user:add">
<a th:href="@{/user/add}">add</a>
</div>
<div align="center" Shiro:hasPermission="user:update">
<a th:href="@{/user/update}">update</a>
</div>
</body>
</html>
Copy the code
/ / certification
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("Executed =" Authenticated doGetAuthenticationInfo");
// Create a token
// The user name and password are obtained from the database
UsernamePasswordToken usertoken = (UsernamePasswordToken) token;
// Connect to a real database
User user = userService.queryUserByName(usertoken.getUsername());// Get the user name
if(user==null) {// The account was not found
return null;
}
Subject currentSubject = SecurityUtils.getSubject();
Session session = currentSubject.getSession();
session.setAttribute("loginUser", user);
// Password authentication, shiro does
return new SimpleAuthenticationInfo("",user.getPwd(),"");
}
Copy the code