Integration of Shiro in spring boot

InfoQ 2021-01-24 13:59:37
integration shiro spring boot


{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Shiro Is a powerful 、 Easy to use Java Security framework , Mainly used for more convenient authentication , to grant authorization , encryption , Conversation management and so on , Can provide security for any application . This course mainly introduces Shiro Authentication and authorization functions of .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1. Shiro Three core components ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Shiro There are three core components :","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Subject","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SecurityManager","attrs":{}}],"attrs":{}},{"type":"text","text":" and ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Realm","attrs":{}}],"attrs":{}},{"type":"text","text":". Let's look at the relationship between them first .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d7/d725f5bbb43c71695870b29bab8064de.webp","alt":" The relationship between the three core components ","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"Subject: Subject of certification . It contains two messages :Principals and Credentials. Take a look at these two messages .","attrs":{}}]}],"attrs":{}}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Principals: identity . It can be a user name , mail , Cell phone number and so on , Used to identify the identity of a login principal ; ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Credentials: voucher . There are common passwords , Digital certificates and so on .","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" To put it bluntly , It's something that needs certification , The most common is the user name and password , For example, when a user logs in ,Shiro Need to be authenticated , Need Subject Subject of certification .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"SecurityManager: Security administrator . This is a Shiro The heart of the architecture , It's like Shiro It's the same umbrella as all the original parts inside . We usually configure... In projects SecurityManager, Most of the energy of developers is mainly in Subject On the certification body . We are in contact with Subject When interacting , It's actually SecurityManager Do something safe behind the scenes .","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"Realm:Realm It's a domain , It's a connection Shiro And concrete application of the bridge , When you need to interact with secure data , Like user accounts 、 Access control, etc ,Shiro From one or more Realm To find the . We can Realm as DataSource, Secure data source , We usually customize it ourselves Realm, In the custom Realm in , We usually get authentication related information from the database , This is customized below Realm The section will elaborate on .","attrs":{}}]}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1. Shiro Identity and authority authentication ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1.2 Shiro Identity Authentication ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Let's analyze Shiro The process of identity authentication , Take a look at an official certification map :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8d/8d81e16b08fcd5c36b824fedbc180f31.png","alt":" The authentication process ","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Step1: The application code is calling ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Subject.login(token)","attrs":{}}],"attrs":{}},{"type":"text","text":" After the method , Pass in... That represents the identity and credentials of the end user AuthenticationToken example token. ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Step2: take Subject Instance delegate to the application SecurityManager(Shiro Safety management ) To start the actual certification work . Here's the real certification work . ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Step3,4,5: then SecurityManager According to the specific realm Go for security certification . As you can see from the diagram ,realm You can customize (Custom Realm).","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1.3 Shiro Permission authentication ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Permission authentication , That's access control , Control who has access to what resources in your application . In authority authentication , The three core elements are : jurisdiction , Roles and users .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" jurisdiction (permission): The right to operate resources , Like visiting a page , And the addition of data to a module , modify , Delete , The right to see ; ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" role (role): It refers to the role of the user , A role can have multiple permissions ; ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" user (user): stay Shiro in , On behalf of the user accessing the system , As mentioned above Subject Subject of certification .","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The relationship between them can be shown in the figure below : ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/67/6782d33681a7cc5d43e52955ba70c7f6.png","alt":" user 、 The relationship between roles and permissions ","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" A user can have multiple roles , And different roles can have different permissions , You can also have the same permissions . For example, now there are three characters ,1 It's a normal character ,2 It's also a normal character ,3 It's the administrator , role 1 You can only view information , role 2 You can only add information , Administrators can , And you can delete information , Something like this .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2. Spring Boot Integrate Shiro The process ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.1 Dependency import ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Spring Boot 2.0.3 Integrate Shiro You need to import the following starter rely on :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"xml"},"content":[{"type":"text","text":"\n org.apache.shiro\n shiro-spring\n 1.4.0\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.2 Database table data initialization ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Here are three tables : User table 、 Role table and permission table , Actually in demo in , We can simulate it ourselves , There is no need to build a table , But to get closer to reality , We still join in mybatis, To manipulate the database . Here's the script for the database table .","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"sql"},"content":[{"type":"text","text":"CREATE TABLE `t_role` (\n `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',\n `rolename` varchar(20) DEFAULT NULL COMMENT ' Character name ',\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8\n\nCREATE TABLE `t_user` (\n `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' With the head of the household key ',\n `username` varchar(20) NOT NULL COMMENT ' user name ',\n `password` varchar(20) NOT NULL COMMENT ' password ',\n `role_id` int(11) DEFAULT NULL COMMENT ' Foreign key link role surface ',\n PRIMARY KEY (`id`),\n KEY `role_id` (`role_id`),\n CONSTRAINT `t_user_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8\n\nCREATE TABLE `t_permission` (\n `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',\n `permissionname` varchar(50) NOT NULL COMMENT ' Authority Name ',\n `role_id` int(11) DEFAULT NULL COMMENT ' Foreign key link role',\n PRIMARY KEY (`id`),\n KEY `role_id` (`role_id`),\n CONSTRAINT `t_permission_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" among ,t","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"user,t","attrs":{}},{"type":"text","text":"role and t_permission, Store user information separately , Role information and permission information , After the table is set up , Let's insert some test data into the table .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"t_user surface :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|id|username|password|role_id|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|:--:|:--:|:--:|:--:|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|1|csdn1|123456|1|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|2|csdn2|123456|2|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|3|csdn3|123456|3|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"t_role surface :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|id|rolename|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|:--:|:--:|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|1|admin|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|2|teacher|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|3|student|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"t_permission surface :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|id|permissionname|role_id|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|:--:|:--:|:--:|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|1|","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"user:*","attrs":{}}],"attrs":{}},{"type":"text","text":"|1|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|2|","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"student:*","attrs":{}}],"attrs":{}},{"type":"text","text":"|2|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Explain the permissions here :","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"user:*","attrs":{}}],"attrs":{}},{"type":"text","text":" Indicates that the permission can be ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"user:create","attrs":{}}],"attrs":{}},{"type":"text","text":" Or other ,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"*","attrs":{}}],"attrs":{}},{"type":"text","text":" Place represents a place holder , We can define ourselves , The details are as follows Shiro The configuration says .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.2 Customize Realm","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" With database tables and data , We started customizing realm, Customize realm Need to inherit AuthorizingRealm class , Because this class encapsulates many methods , It is also inherited step by step from Realm Class , Inherited AuthorizingRealm After the class , Two methods need to be overridden :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"doGetAuthenticationInfo()","attrs":{}}],"attrs":{}},{"type":"text","text":" Method : Used to authenticate the currently logged in user , Get authentication information ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"doGetAuthorizationInfo()","attrs":{}}],"attrs":{}},{"type":"text","text":" Method : It is used to grant permissions and roles to the current successful login user ","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The specific implementation is as follows , I put the relevant explanation in the comments of the code , This is more convenient and intuitive :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"/**\n * Customize realm\n * @author shengwu ni\n */\npublic class MyRealm extends AuthorizingRealm {\n\n @Resource\n private UserService userService;\n\n @Override\n protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {\n // Get username \n String username = (String) principalCollection.getPrimaryPrincipal();\n SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();\n // Set the role for the user , Role information exists t_role From the table \n authorizationInfo.setRoles(userService.getRoles(username));\n // Set permissions for the user , Permission information exists t_permission From the table \n authorizationInfo.setStringPermissions(userService.getPermissions(username));\n return authorizationInfo;\n }\n\n @Override\n protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {\n // according to token Get username , If you don't know what to do token How did it come from , I don't care , The following will explain \n String username = (String) authenticationToken.getPrincipal();\n // Query the user from the database according to the user name \n User user = userService.getByUsername(username);\n if(user != null) {\n // Save the current user to session in \n SecurityUtils.getSubject().getSession().setAttribute(\"user\", user);\n // Pass in a user name and password for authentication , And return the authentication information \n AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), \"myRealm\");\n return authcInfo;\n } else {\n return null;\n }\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" It can be seen from the above two methods that : Authentication is based on the user name entered by the user, first find out the user corresponding to the user name from the database , There is no password involved at this time , When it comes to this step , Even if the user entered the wrong password , You can also find out the user , Then encapsulate the user's correct information into authcInfo Back to Shiro, The next step is Shiro Thing , It will check the user name and password entered by the user's front desk according to the real information , It's time to check the password , If the verification is passed, let the user log in , Otherwise, jump to the specified page . Empathy , Permission verification is also based on the user name to obtain the role and permission related to the user name from the database , Then encapsulate the authorizationInfo Back to Shiro.","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.3 Shiro To configure ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Self defined realm Well done. , Next we need to be right Shiro configured . We mainly configure three things : Customize realm、 Safety manager SecurityManager and Shiro filter . as follows :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Configure customization realm:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Configuration\npublic class ShiroConfig {\n\n private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);\n\n /**\n * Inject custom realm\n * @return MyRealm\n */\n @Bean\n public MyRealm myAuthRealm() {\n MyRealm myRealm = new MyRealm();\n logger.info(\"====myRealm Registration completed =====\");\n return myRealm;\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Configure security manager SecurityManager:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Configuration\npublic class ShiroConfig {\n\n private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);\n\n /**\n * Inject Security Manager \n * @return SecurityManager\n */\n @Bean\n public SecurityManager securityManager() {\n // Will customize realm Add in \n DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(myAuthRealm());\n logger.info(\"====securityManager Registration completed ====\");\n return securityManager;\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" To configure SecurityManager when , You need to customize the above realm added , In this case Shiro Will go to custom realm in .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" To configure Shiro filter :","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Configuration\npublic class ShiroConfig {\n\n private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);\n \n /**\n * Inject Shiro filter \n * @param securityManager Safety manager \n * @return ShiroFilterFactoryBean\n */\n @Bean\n public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {\n // Definition shiroFactoryBean\n ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();\n\n // Set up custom securityManager\n shiroFilterFactoryBean.setSecurityManager(securityManager);\n\n // Set the default login url, If the authentication fails, the url\n shiroFilterFactoryBean.setLoginUrl(\"/login\");\n // Set the link to jump after success \n shiroFilterFactoryBean.setSuccessUrl(\"/success\");\n // Set up unauthorized interface , If permission authentication fails, the url\n shiroFilterFactoryBean.setUnauthorizedUrl(\"/unauthorized\");\n\n // LinkedHashMap Is ordered , Make a sequential interceptor configuration \n Map filterChainMap = new LinkedHashMap<>();\n\n // Configure addresses that can be accessed anonymously , You can add it according to the actual situation , Release some static resources, etc ,anon To release \n filterChainMap.put(\"/css/**\", \"anon\");\n filterChainMap.put(\"/imgs/**\", \"anon\");\n filterChainMap.put(\"/js/**\", \"anon\");\n filterChainMap.put(\"/swagger-*/**\", \"anon\");\n filterChainMap.put(\"/swagger-ui.html/**\", \"anon\");\n // Sign in url release \n filterChainMap.put(\"/login\", \"anon\");\n\n // “/user/admin” The first one needs authentication ,authc Means to authenticate \n filterChainMap.put(\"/user/admin*\", \"authc\");\n // “/user/student” The first one needs role authentication , yes “admin” To allow \n filterChainMap.put(\"/user/student*/**\", \"roles[admin]\");\n // “/user/teacher” The first one needs permission authentication , yes “user:create” To allow \n filterChainMap.put(\"/user/teacher*/**\", \"perms[\\\"user:create\\\"]\");\n\n // To configure logout filter \n filterChainMap.put(\"/logout\", \"logout\");\n\n // Set up shiroFilterFactoryBean Of FilterChainDefinitionMap\n shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);\n logger.info(\"====shiroFilterFactoryBean Registration completed ====\");\n return shiroFilterFactoryBean;\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" To configure Shiro When filtering, a security manager is passed in , It can be seen that , It's a set of rings ,reaml -> SecurityManager -> filter. In the filter , We need to define one shiroFactoryBean, And then SecurityManager added , Combined with the above code, we can see that , The main things to be configured are :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Default login url: If the authentication fails, the url","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" After the authentication is successful, you have to jump url","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" If permission authentication fails, the url","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" What needs to be intercepted or released url: These are all in one map in ","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" As you can see from the above code , stay map in , For different url, There are different authority requirements , Here is a summary of several common permissions .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|Filter| explain |","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|:--:|:--:|","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|anon| Open access , It can be understood as anonymous users or tourists , Directly accessible |","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|authc| You need authentication |","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|logout| Cancellation , After execution, it will jump to ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"shiroFilterFactoryBean.setLoginUrl();","attrs":{}}],"attrs":{}},{"type":"text","text":" Set up url, The landing page |","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|roles[admin]| You can write multiple parameters , It means that one or some characters can pass through , Write... For multiple parameters roles[\"admin,user\"], When there are more than one parameter, each parameter must pass before it is passed |","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"|perms[user]| You can write multiple parameters , Indicates that one or some permissions are required to pass through , Write... For multiple parameters perms[“user, admin”], When there are more than one parameter, each parameter must pass before it is passed |","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.4 Use Shiro authentication ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Come here , We are right. Shiro I've finished all the preparations for the meeting , So let's start using Shiro Carry out certification work . Let's design a few interfaces first :","attrs":{}}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Interface 1 : Use ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"http://localhost:8080/user/admin","attrs":{}}],"attrs":{}},{"type":"text","text":" To verify Authentication ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Interface II : Use ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"http://localhost:8080/user/student","attrs":{}}],"attrs":{}},{"type":"text","text":" To verify role authentication ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Interface three : Use ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"http://localhost:8080/user/teacher","attrs":{}}],"attrs":{}},{"type":"text","text":" To verify authority authentication ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Interface 4 : Use ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"http://localhost:8080/user/login","attrs":{}}],"attrs":{}},{"type":"text","text":" To achieve user login ","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" And then let's take a look at the authentication process :","attrs":{}}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Process 1 : Direct access interface one ( Not logged in at this time ), Authentication failed , Jump to login.html Page allows users to log in , Login will request interface 4 , Realize user login function , here Shiro The user information has been saved .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Process 2 : Access interface one again ( At this point, the user has logged in ), Authentication success , Jump to success.html page , Display user information .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Process 3 : Access interface 2 , Test whether the role authentication is successful .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Process 4 : Access interface three , Test whether authority authentication is successful .","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.4.1 identity 、 role 、 Authority authentication interface ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Controller\n@RequestMapping(\"/user\")\npublic class UserController {\n\n /**\n * Authentication test interface \n * @param request\n * @return\n */\n @RequestMapping(\"/admin\")\n public String admin(HttpServletRequest request) {\n Object user = request.getSession().getAttribute(\"user\");\n return \"success\";\n }\n\n /**\n * Role authentication test interface \n * @param request\n * @return\n */\n @RequestMapping(\"/student\")\n public String student(HttpServletRequest request) {\n return \"success\";\n }\n\n /**\n * Authority authentication test interface \n * @param request\n * @return\n */\n @RequestMapping(\"/teacher\")\n public String teacher(HttpServletRequest request) {\n return \"success\";\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" These three interfaces are simple , Directly return to the designated page to display , As long as the authentication is successful, it will jump normally , If authentication fails , I'll jump to the above ShrioConfig Display the page configured in .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.4.2 User login interface ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Controller\n@RequestMapping(\"/user\")\npublic class UserController {\n\n /**\n * User login interface \n * @param user user\n * @param request request\n * @return string\n */\n @PostMapping(\"/login\")\n public String login(User user, HttpServletRequest request) {\n\n // Create... Based on user name and password token\n UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());\n // obtain subject Subject of certification \n Subject subject = SecurityUtils.getSubject();\n try{\n // Start certification , This step will jump to our custom realm in \n subject.login(token);\n request.getSession().setAttribute(\"user\", user);\n return \"success\";\n }catch(Exception e){\n e.printStackTrace();\n request.getSession().setAttribute(\"user\", user);\n request.setAttribute(\"error\", \" Wrong user name or password !\");\n return \"login\";\n }\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Let's focus on the login interface , First, according to the user name and password from the front end , Create a token, And then use SecurityUtils To create an authentication principal , Next, start calling ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"subject.login(token)","attrs":{}}],"attrs":{}},{"type":"text","text":" It's time for authentication , Notice that we've just created token, As noted in the note , This step will jump to our custom realm in , Get into ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"doGetAuthenticationInfo","attrs":{}}],"attrs":{}},{"type":"text","text":" Method , So here we go , You'll see which parameter in the method token 了 . And then it's like the above analysis , Start Authentication .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"2.4.3 Test it ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Last , Start project , Test it :","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Browser request ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"http://localhost:8080/user/admin","attrs":{}}],"attrs":{}},{"type":"text","text":" Will be authenticated , Because I'm not logged in at this time , So I'll jump to IndexController Medium ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"/login","attrs":{}}],"attrs":{}},{"type":"text","text":" Interface , And then jump to ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"login.html","attrs":{}}],"attrs":{}},{"type":"text","text":" Page let's log in , Use the user name and password as csdn1/123456 After login , We request in browser ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"http://localhost:8080/user/student","attrs":{}}],"attrs":{}},{"type":"text","text":" Interface , Will do role authentication , Because in the database csdn1 My user role is admin, So it's consistent with the configuration , Certification by ; We ask again ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"http://localhost:8080/user/teacher","attrs":{}}],"attrs":{}},{"type":"text","text":" Interface , Will be authenticated , Because in the database csdn1 The user rights of are ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"user:*","attrs":{}}],"attrs":{}},{"type":"text","text":", Satisfy the ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"user:create","attrs":{}}],"attrs":{}},{"type":"text","text":", So the certification passed .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Next , Let's click exit , The system will log off and let us log in again , We use csdn2 This user logs in , Repeat the above operation , When performing the two steps of role authentication and permission Authentication , It's not certified , Because in the database csdn2 The roles and permissions of this user are different from those in the configuration , So the certification didn't pass .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3. summary ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" This section mainly introduces Shiro Security framework and Spring Boot Integration of . First introduced Shiro The three core components of have their role ; Then it introduces Shiro Identity authentication 、 Role authentication and authority authentication ; Finally, combined with the code , In detail Spring Boot How to integrate Shiro Of , And designed a set of test process , Step by step analysis Shiro Working process and principle of , Let readers more intuitively experience Shiro The whole workflow of .Shiro It's widely used , I hope readers can master it , And can be applied to the actual project .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Course source code download address :","attrs":{}},{"type":"link","attrs":{"href":"https://gitee.com/eson15/springboot_study","title":""},"content":[{"type":"text","text":" Poke me to download ","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://javamana.com/2021/01/20210124134826738A.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云