catalogue
Shiro integrated in SpringBoot
4.ShiroConfig realm object needs to be customized
Intercept: ShiroConfig--ShiroFilterFactoryBean
Shrio uses user authentication
6.UserRealm get data from database
1. Authorize ShiroConfig--ShiroFilterFactoryBean
2.noAuth.html # unauthorized page
5. Get authorization from database
Login succeeded in obtaining session
Shiro core three objects
- Subject user
- SecurityManager manages all users
- Real connection data
Quickstart core:
//Get the current user object Subject Subject currentUser = SecurityUtils.getSubject();
//Get session from current user Session session = currentUser.getSession();
//Judge whether the user is authenticated if (!currentUser.isAuthenticated()) { //Get the authentication access information of the current user currentUser.getPrincipal()
//Determine whether the user has a role if (currentUser.hasRole("schwartz")) {
//Check whether you have any permissions if (currentUser.isPermitted("lightsaber:wield")) {
//Write off currentUser.logout();
- Apache Shiro is a Java Security (permission) framework.
- Shiro can easily develop good enough applications, which can be used not only in Java se environment, but also in Java EE environment.
- Shiro can complete, authentication, authorization, encryption, session management, Web integration, caching, etc.
- Download address: Apache Shiro | Simple. Java. Security.
- GitHub: GitHub - apache/shiro: Apache Shiro
- Authentication: identity authentication, login, and verify whether the user has the corresponding identity;
- Authorization: authorization, that is, permission verification. It verifies whether an authenticated user has a certain permission, that is, it determines whether the user can perform any operations, such as verifying whether a user has a certain role, or fine-grained verifying whether a user has a certain permission on a resource!
- Session Manager: session management, that is, after a user logs in, it is the first session. Before exiting, all its information is in the session; The session can be an ordinary Java se environment or a Web environment;
- Cryptography: encryption to protect the security of data. For example, the password is encrypted and stored in the database instead of plaintext;
- Web Support: Web Support, which can be easily integrated into the web environment;
- Caching: caching. For example, after a user logs in, the user information, roles and permissions do not need to be checked every time, which can improve efficiency
- Concurrency: Shiro supports concurrent verification of multithreaded applications, that is, if you start another thread in one thread, you can automatically propagate permissions to the past
- Testing: provide test support;
- Run As: allow one user to pretend to be the identity of another user (if they allow it);
- Remember Me: Remember Me, this is a very common function, that is, after logging in once, you don't need to log in next time
1.3 Shiro architecture (external)
- Subject: any 'user' who can interact with the application;
- Security Manager: equivalent to dispatcher servlet in spring MVC; It is the heart of Shiro. All specific interactions are controlled through security manager. It manages all subjects and is responsible for authentication, authorization, session and cache management.
- Authenticator: responsible for Subject authentication. It is an extension point and can be customized; Authentication Strategy can be used, that is, when the user has passed the authentication;
- Authorizer: authorizer, that is, access controller, which is used to determine whether the subject has permission to perform corresponding operations; That is, it controls the functions that users can access in the application;
- Realm: there can be one or more realms, which can be considered as data sources of security entities, that is, those used to obtain security entities can be implemented in JDBC or memory, etc., which are provided by users; Therefore, we generally need to implement our own realm in applications
- Session manager: a component that manages the session life cycle. Shiro can be used not only in the Web environment, but also in the ordinary Java se environment
- CacheManager: cache controller to manage the cache of users, roles, permissions, etc; Because these data are rarely changed, the performance of access can be improved after being put into the cache;
- Cryptography: password module. Shiro improves some common encryption components for password encryption, decryption, etc
First Shiro program
Shiro tutorial: 10 Minute Tutorial on Apache Shiro | Apache ShiroApache Shiro Tutorial | Apache Shiro10 Minute Tutorial on Apache Shiro | Apache Shiro
hello-shrio
1.pom.xml
<dependencies> <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.7.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.1</version> <scope>runtime</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.1</version> <scope>runtime</scope> </dependency> <!-- https://mvnrepository.com/artifact/log4j/log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> <scope>runtime</scope> </dependency> </dependencies>
2. Write Shiro configuration
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
shiro.ini
[users] root = secret, admin guest = guest, guest presidentskroob = 12345, president darkhelmet = ludicrousspeed, darklord, schwartz lonestarr = vespa, goodguy, schwartz # ----------------------------------------------------------------------------- # Roles with assigned permissions # roleName = perm1, perm2, ..., permN # ----------------------------------------------------------------------------- [roles] admin = * schwartz = lightsaber:* goodguy = winnebago:drive:eagle5
3,Quickstart
import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Simple Quickstart application showing how to use Shiro's API. * * @since 0.9 RC2 */ public class Quickstart { //Use the log interface to use log output private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class); public static void main(String[] args) { // The easy way to create a Shiro SecurityManager with configured // realms, users, roles and permissions is to use the simple INI config. Domains, users, roles and permissions are configured using simple ini. Is to load Shiro Ini configuration file // We'll do that by using a factory that can ingest a .ini file and we read the configuration file by factory default // return a SecurityManager instance: returns a SecurityManager instance // Use the shiro.ini file at the root of the classpath Ini root directory is classpath // (file: and url: prefixes load from files and urls respectively): // Factory mode Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); // for this simple example quickstart, make the SecurityManager / / for this simple quick start example, let SecurityManager // accessible as a JVM singleton. Most applications wouldn't do this / / accessible JVM singletons. Most applications don't do that // and instead rely on their container configuration or web.xml for / / depends on their container configuration or web xml // webapps. That is outside the scope of this simple quickstart, so // webapps. This is beyond the scope of a simple quick start, so // we'll just do the bare minimum so you can continue to get a feel // for things. // Right thing. SecurityUtils.setSecurityManager(securityManager); System.out.println("--------------Dead code above-----------------------"); System.out.println("Core code"); //Get the current user object Subject Subject currentUser = SecurityUtils.getSubject(); //Get session from current user Session session = currentUser.getSession(); session.setAttribute("someKey", "aValue"); String value = (String) session.getAttribute("someKey"); if (value.equals("aValue")) { log.info("Subject=> session [" + value + "]"); } //Judge whether the user is authenticated if (!currentUser.isAuthenticated()) { //Token: a token is generated by account and password UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); token.setRememberMe(true); //Set remember me try { currentUser.login(token); //Execute force login operation~ } catch (UnknownAccountException uae) { //Unknown user name does not exist log.info("There is no user with username of " + token.getPrincipal()); } catch (IncorrectCredentialsException ice) { //Wrong password log.info("Password for account " + token.getPrincipal() + " was incorrect!"); } catch (LockedAccountException lae) { //The user is locked, for example, 5 times, and the password is incorrect 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) { //Authentication exception //unexpected condition? error? } } //say who they are: //print their identifying principal (in this case, a username): log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); // Get the authentication access information of the current user //test a role: //Determine whether the user has a role if (currentUser.hasRole("schwartz")) { log.info("May the Schwartz be with you!"); } else { log.info("Hello, mere mortal."); } //Coarse grain size //test a typed permission (not instance-level) if (currentUser.isPermitted("lightsaber:wield")) { //Check whether you have any permissions Shiro drive:eagle5 in ini log.info("You may use a lightsaber ring. Use it wisely."); } else { log.info("Sorry, lightsaber rings are for schwartz masters only."); } //Fine grained //a (very powerful) Instance Level permission: if (currentUser.isPermitted("winnebago:drive:eagle5")) { //Do you have higher permissions 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!"); } //cancellation currentUser.logout(); //end System.exit(0); } }
Core:
//Get the current user object Subject Subject currentUser = SecurityUtils.getSubject();
//Get session from current user Session session = currentUser.getSession();
//Judge whether the user is authenticated if (!currentUser.isAuthenticated()) { //Get the authentication access information of the current user currentUser.getPrincipal()
//Determine whether the user has a role if (currentUser.hasRole("schwartz")) {
//Check whether you have any permissions if (currentUser.isPermitted("lightsaber:wield")) {
//Write off currentUser.logout();
result:
Shiro integrated in SpringBoot
Environment construction
1.pom.xml
<!-- spring integration shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.7.1</version> </dependency>
2.index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://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>
3.MyController
@Controller public class MyController { @RequestMapping({"/", "/index"}) public String toIndex(Model model) { model.addAttribute("msg", "Hello Shiro"); return "index"; } }
4.ShiroConfig realm object needs to be customized
package com.gh.config; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 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.LinkedHashMap; import java.util.Map; /** * Subject: user * SecurityManager: Manage all users * Realm: Connection data */ @Configuration public class ShiroConfig { //3.ShiroFilterFactoryBean //2.DefaultWebSecurityManager //1. Creating a realm object requires customization }
5.UserRealm
extends AuthorizingRealm
//Customize userrealm extensions authoringrealm public class UserRealm extends AuthorizingRealm { //to grant authorization @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("to grant authorization=======>principalCollection"); return null; } //authentication @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("authentication======>authenticationToken"); return null; } }
6.ShiroConfig write backwards
package com.gh.config; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 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.LinkedHashMap; import java.util.Map; /** * Subject: user * SecurityManager: Manage all users * Realm: Connection data */ @Configuration public class ShiroConfig { //3.ShiroFilterFactoryBean @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("webSecurityManager") DefaultWebSecurityManager webSecurityManager) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //Set up security manager bean.setSecurityManager(webSecurityManager); return bean; } //2.DefaultWebSecurityManager @Bean(name = "webSecurityManager") //Do not write default method name public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) { DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager(); webSecurityManager.setRealm(userRealm); return webSecurityManager; } //1. Creating a realm object requires customization @Bean public UserRealm userRealm() { //userRealm1 is equivalent to an alias return new UserRealm(); } }
7. Add page
add.html ,update.html simple page
controller
@RequestMapping("/user/toAdd") public String toAdd() { return "user/add"; } @RequestMapping("/user/toUpdate") public String toUpdate() { return "user/update"; }
index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://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> <a th:href="@{/user/toAdd}">newly added</a> <a th:href="@{/user/toAdd}">newly added</a> </body> </html>
8. Test
User interception
Intercept:
ShiroConfig--ShiroFilterFactoryBean
//Add shiro's built-in interceptor /** * anon: Access without authentication * authc: Authentication is required to access * user: You must have the 'remember me' function to access * perms: You must have permission to access a resource * role: You must have a role permission to access */ //LinkedHashMap is generally used for chain Map<String, String> filterMap = new LinkedHashMap<>(); //to grant authorization filterMap.put("/user/toAdd","authc"); filterMap.put("/user/toUpdate","authc"); //Support wildcards // filterMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(filterMap);
Map<String, String> filterMap = new LinkedHashMap<>(); filterMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(filterMap);
Interception succeeded
Jump to login page
login.html,controller
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Login page</title> </head> <form method="get" th:action="@{/login}"> <p> user name:<input type="text" name="username"/> </p> <p> password:<input type="password" name="password"/> </p> <input type="submit" value="Sign in"/> </form> </body> </html>
@RequestMapping("/toLogin") public String toLogin() { return "login"; }
ShiroConfig--ShiroFilterFactoryBean
//Set login request bean.setLoginUrl("/toLogin");
Shrio uses user authentication
1, MyController
@RequestMapping("/login") public String login(String username, String password, Model model) { System.out.println("===========>"+username); System.out.println("===========>"+password); //Get current user subject Subject user = SecurityUtils.getSubject(); //Encapsulate the user's login data token token UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { user.login(token);//The login method executed. If there is no exception, it indicates that it is OK return "index"; } catch (UnknownAccountException e) { //User name error model.addAttribute("msg","User name error!!!"); return "login"; }catch (IncorrectCredentialsException e){ //Password error model.addAttribute("msg","Password error!!!"); return "login"; } }
Execution: entered the authentication method
II. Certification:
UserRealm
//authentication @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("authentication======>authenticationToken"); UsernamePasswordToken userToken = (UsernamePasswordToken) token;//The login information can be obtained by converting the fixed routine into the Token we know //Assume that the user name and password are retrieved from the database String username = "root"; String password = "123456"; if (!userToken.getUsername().equals(username)){ return null;//Throw an exception UnknownAccountException } /* Three parameters Obtain the authentication of the current user User password Authentication name */ return new SimpleAuthenticationInfo("",password, ""); }
Shrio integrates Mybatis
1.pom.xml
<!-- mysql Database connection dependency --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- druid data source --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <!-- mybatis-springboot --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency>
2.application.yml
# Application service WEB access port server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver name: defaultDataSource username: root password: 123456 url: jdbc:mysql://localhost:3306/mapper?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC type: com.alibaba.druid.pool.DruidDataSource #Spring Boot does not inject these attribute values by default and needs to bind by itself #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 for monitoring statistics interception, stat: monitoring statistics, log4j: logging, wall: defensive sql injection #If allowed, an error will be reported in Java lang.ClassNotFoundException: org. apache. log4j. Priority #Then import log4j dependency. 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
3.pojo
user
@Data @AllArgsConstructor @NoArgsConstructor public class User implements Serializable { private Integer id; private String name; private String pwd; }
4.dao
UserDao
@Repository @Mapper public interface UserDao { /** * Sign in * @param name * @return */ User queryUserByName(String name); }
UserMapper
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.gh.dao.UserDao"> <select id="queryUserByName" resultType="com.gh.pojo.User" parameterType="String"> SELECT * FROM `user` WHERE `name` = #{name} </select> </mapper>
5.service
UserService
public interface UserService { /** * Sign in * @param name * @return */ User queryUserByName(String name); }
UserServiceImpl
@Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public User queryUserByName(String name) { return userDao.queryUserByName(name); } }
Test: application tests
@SpringBootTest class ApplicationTests { @Autowired UserServiceImpl userService; @Test void contextLoads() { System.out.println(userService.queryUserByName("Big white")); } }
6.UserRealm get data from database
//Customize userrealm extensions authoringrealm public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; //to grant authorization @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("to grant authorization=======>principalCollection"); return null; } //authentication @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("authentication======>authenticationToken"); UsernamePasswordToken userToken = (UsernamePasswordToken) token;//We can get the regular login information //Connect to real database User user = userService.queryUserByName(userToken.getUsername()); //Determine whether the user exists if (user == null) { //There is no such person return null; //Throw UnknownAccountException } //Log in successfully and store user information in session Subject currentUser = SecurityUtils.getSubject(); currentUser.getSession().setAttribute("user",currentUser); /* Three parameters Obtain the authentication of the current user User password Authentication name */ //Password authentication shrio~ is encrypted return new SimpleAuthenticationInfo("",user.getPwd(), ""); } }
Authorization
1. Authorize ShiroConfig--ShiroFilterFactoryBean
//Resource permissions filterMap.put("/user/toAdd","perms[user:add]"); // Only users with user: add can access / user/toAdd filterMap.put("/user/toUpdate", "perms[user:update]");
2.noAuth.html # unauthorized page
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1 style="color: red"> Sorry, you don't have permission to access this resource!!! </h1> </body> </html>
3. Set unauthorized requests
ShiroConfig--ShiroFilterFactoryBean
bean.setUnauthorizedUrl("/noAuth");
4. to grant authorization
//to grant authorization @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("to grant authorization=======>principalCollection"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermission("user:add"); return info; }
5. Get authorization from database
Add a database perms field to the user table
//to grant authorization @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("to grant authorization=======>principalCollection"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermission("user:add"); //Get the currently logged in object Subject subject = SecurityUtils.getSubject(); User currentUser = (User) subject.getPrincipal(); //Get User object //Set the permissions of the current user info.addStringPermission(currentUser.getPerms()); return info; }
Note: authentication binding is required
Permission selection
pom.xml
<!-- shiro-thymeleaf --> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
Configuration required: ShiroConfig can be used
//Shirodialect Shiro integrated thymeleaf @Bean public ShiroDialect getShiroDialect(){ return new ShiroDialect(); }
index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://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> <!--from session Judgment value--> <div th:if="${session.loginUser}==null"> <a th:href="@{/toLogin}">Sign in</a> </div> <p th:text="${msg}"></p> <div shiro:hasPermission="user:add"> <!--hasPermission Do you have this permission--> <a th:href="@{/user/toAdd}">newly added</a> </div> <div shiro:hasPermission="user:update"> <a th:href="@{/user/toUpdate}">modify</a> </div> </body> </html>
Login succeeded in obtaining session
UserRealm / / authentication in progress
//Log in successfully and store user information in session Subject currentSubject = SecurityUtils.getSubject(); Session session = currentSubject.getSession(); session.setAttribute("loginUser",currentUser);
Catalogue
ShiroConfig
package com.gh.config; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 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.LinkedHashMap; import java.util.Map; /** * Subject: user * SecurityManager: Manage all users * Realm: Connection data */ @Configuration public class ShiroConfig { //3.ShiroFilterFactoryBean @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("webSecurityManager") DefaultWebSecurityManager webSecurityManager) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //Set up security manager bean.setSecurityManager(webSecurityManager); //Add shiro's built-in interceptor /** * anon: Access without authentication * authc: Authentication is required to access * user: You must have the 'remember me' function to access * perms: You must have permission to access a resource * role: You must have a role permission to access */ //LinkedHashMap is generally used for chain Map<String, String> filterMap = new LinkedHashMap<>(); //to grant authorization filterMap.put("/user/toAdd","authc"); filterMap.put("/user/toUpdate","authc"); //Support wildcards // filterMap.put("/user/*","authc"); //Under normal resource permissions, unauthorized resources will jump to the unauthorized page filterMap.put("/user/toAdd","perms[user:add]"); // Only users with user: add can access / user/toAdd filterMap.put("/user/toUpdate","perms[user:update]"); bean.setFilterChainDefinitionMap(filterMap); //Set login request bean.setLoginUrl("/toLogin"); //Set unauthorized requests bean.setUnauthorizedUrl("/noAuth"); return bean; } //2.DefaultWebSecurityManager @Bean(name = "webSecurityManager") //Do not write default method name public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) { DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager(); webSecurityManager.setRealm(userRealm); return webSecurityManager; } //1. Creating a realm object requires customization @Bean public UserRealm userRealm() { //userRealm1 is equivalent to an alias return new UserRealm(); } //Shirodialect Shiro integrated thymeleaf @Bean public ShiroDialect getShiroDialect(){ return new ShiroDialect(); } }
UserRealm
package com.gh.config; import com.gh.pojo.User; import com.gh.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; //Customize userrealm extensions authoringrealm public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; //to grant authorization @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("to grant authorization=======>principalCollection"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermission("user:add"); //Get the currently logged in object Subject subject = SecurityUtils.getSubject(); User currentUser = (User) subject.getPrincipal(); //Get User object //Set the permissions of the current user info.addStringPermission(currentUser.getPerms()); return info; } //authentication @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("authentication======>authenticationToken"); UsernamePasswordToken userToken = (UsernamePasswordToken) token;//The login information can be obtained by converting the fixed routine into the Token we know //Connect to real database User user = userService.queryUserByName(userToken.getUsername()); //Determine whether the user exists if (user == null) { //There is no such person return null; //Throw UnknownAccountException } //Log in successfully and store user information in session Subject currentSubject = SecurityUtils.getSubject(); Session session = currentSubject.getSession(); session.setAttribute("loginUser",user); /* Three parameters Obtain the authentication of the current user User password Authentication name */ //Password authentication shrio~ is encrypted return new SimpleAuthenticationInfo(user,user.getPwd(), ""); } }
MyController
package com.gh.controller; 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.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class MyController { @RequestMapping({"/", "/index"}) public String toIndex(Model model) { model.addAttribute("msg", "Hello Shiro"); return "index"; } @RequestMapping("/user/toAdd") public String toAdd() { return "user/add"; } @RequestMapping("/user/toUpdate") public String toUpdate() { return "user/update"; } @RequestMapping("/toLogin") public String toLogin() { return "login"; } @RequestMapping("/login") public String login(String username, String password, Model model) { System.out.println("===========>"+username); System.out.println("===========>"+password); //Get current user subject Subject user = SecurityUtils.getSubject(); //Encapsulate the user's login data token token UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { user.login(token);//The login method executed. If there is no exception, it indicates that it is OK return "index"; } catch (UnknownAccountException e) { //User name error model.addAttribute("msg","User name error!!!"); return "login"; }catch (IncorrectCredentialsException e){ //Password error model.addAttribute("msg","Password error!!!"); return "login"; } } @RequestMapping("/noAuth") public String author(){ return "noAuth"; } }