This is the fourth day of my participation in the More text Challenge. For details, see more text Challenge
This article is participating in the “Java Theme Month – Java Development in action”. See the link to the event for more details
Shiros is one of the common toolkits used in our development to implement permission control
Shiros is a tool kit commonly used in our development to implement permission control. It mainly includes authentication, authorization, encryption, session management, integration with the Web, caching and other functions. I am engaged in JavaWeb work, and I often encounter projects that need to implement permission control. Before, we relied on querying data to obtain list Mosaic display, and there were also problems of timely judgment of permission. Now with Shiros, we can set permission uniformly, and the implementation of Shrios is also very simple. Let’s take a look at the implementation steps
The web.xml configuration
- Because we integrate with Spring, which is basically an XML file for a Web project. So we configure shiros’ filtering interception in web.xml. Normally, we need to configure Shiro’s filter in front of all the filters, of course, and the encodingFilter before and after the filter is not distinguished. Because they don’t affect each other.
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <! -- the default value is false, meaning that the life cycle is managed by SpringApplicationContext, and true means that the life cycle is managed by servlet container --> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>Copy the code
- Well, this is where Shiro is integrated into the Spring project. What? Yes, it’s that simple. Shiro is integrated into the project at this stage. Integrated integration, but to achieve the full effect of course we still need to continue to configure. Keep in mind that my shiroq filter is called shiroFilter(useful later). Next, we need to configure Shiro in the spring configuration file application. XML. In my project, my Spring configuration file is spring-service.xml. In addition, spring-shiro. XML is introduced in spring-service. XML, which means that shiro is configured in the spring-shiro.
The final source code is downloaded at the end
spring-shiro.xml
- We’ll look at the configuration of spring-shiro.xml in the future, but I’ll use a flashback to explain it, which I think will help us understand the code better. First of all, remember the filter configured in web.xml, named shiroFilter, through which the spring-shiro.xml configuration file is expanded. The first filter we configure in web.xml is actually configuring ShiroFilterFactoryBean, so in this case we need to define ShiroFilterFactoryBean as shiroFilter
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <! -- Shiro's core security interface, this property is required --> <property name="securityManager" ref="securityManager"/> <! <property name="loginUrl" value="/login.html"/> <property name="loginUrl" value="/login.html"/> <! --> <property name="successUrl" value="/index.html"/> <! -- Connections displayed when a user accesses a resource that is not authorized for the user --> <! If you want to test this property more obviously, you can change its value, such as unauthor.jsp, and then log in with [xuan Jade] and go to /admin/ listuser.jsp and see the browser display unauthor.jsp --> <property name="unauthorizedUrl" value="/login.html" /> <! -- Shiro connection constraint configuration, i.e. filter chain definition --> <! - here to cooperate with me this article to understand the role of each filter even http://blog.csdn.net/jadyer/article/details/12172839 - > <! - value below the value of the first '/' on behalf of the path is relative to it. The getContextPath () value to -- > <! -- anon: The filter is empty and does nothing, where the * after the.do and.jsp is a parameter, such as login.jsp? Main this --> <! - authc: Page under the filter must be validated before they can visit, it is Shiro built-in an interceptor org.. Apache Shiro. Web. Filter. Authc. FormAuthenticationFilter - > < property name="filterChainDefinitions"> <value> /statics/**=anon /login.html=anon /sys/schedule.html=perms[sys:schedule:save] /sys/login=anon /captcha.jpg=anon /**=authc </value> </property> </bean>Copy the code
- The “filterChainDefinitions” attribute is defined by the “filterChainDefinitions” attribute. The value is the page permissions that we control. FilterChainDefinitions: The principle of filterChainDefinitions is to search in order and stop searching once you find a page that meets the requirements. So we need to set the pages with wildcards at the end. It is in the configuration above
/sys/schedule.html=perms[sys:schedule:save]
To access schedule. HTML you must have the sys:schedule:save permission. As to where this permission is configured. Let me give you a hint here. Fetch in Realm
- In the above configuration, our securityManager attribute is the Shiro security core configuration interface, which we need to fill in by ourselves. In this configuration, we need to implement our authentication, because our authentication permission must be different for different projects. So this is the only code interface that Shiro gives us, and we only need to provide our own authentication and role permission assignment.
<! -- Shiro uses the Session of the Servlet container by default. You can specify using Shiro's native Session via the sessionMode attribute --> <! <property name="sessionMode" value="native"/> --> <bean id="securityManager" --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm"/> </bean>Copy the code
- So here comes a realm, and this realm is where we implement permissions and authentication. We just need to use Spring to specify our implementation class as a realm
<bean id="userRealm" class="io.renren.shiro.UserRealm"/>
Copy the code
- Before we get into UserRealm, let’s look at what shir’s default realm logic looks like
- Usually we only need to inherit the AuthorizingRealm, because AuthorizingRealm inherits the AuthenticatingRealm, so we only need to inherit the AuthorizingRealm, We can override the authorization and authentication methods that implement permission management.
-
Let’s start by looking at what we should note about authenticated logins
-
Several exceptions occur during login authentication in doGetAuthenticationInfo
- UnknownAccountException: The obtained user is empty
- LockedAccountException: This user is locked
- IncorrectCredentialsException: password is not correct (recommended prompt for the user name or password error. Safety considerations)
- ExcessiveAttemptsException: wrong password too many times (now a lot of websites have related operations)
- Finally, the user information is assembled by user name + plaintext password + getName in Reaml
-
Login authentication is about these points, and the second is the permission assignment, doGetAuthorizationInfo(authorization). In the doGetAuthorizationInfo, we use the identity collection PrincipalCollection, When we have only one Reaml configured we can get the Reaml just passed in through the getPrimaryPrincipal method in the PrincipalCollection. However, when multiple ReamLs are configured, the user names of all reamLs can be obtained through getRealmNames in PrincipalCollection.
-
Then through the user name to the database access menu. Finally, return a SimpleAuthorization information with roles and permissions, meaning which permissions the following roles have. You can also not specify a role if you only have one, using setStringPermissions +setRoles respectively.
-
At this point, Shiro’s configuration is complete.
-
Another aspect of Shiro’s configuration is that it handles shiro’s lifecycle and enables Shiro’s annotations, which will not be explained here
<! - Shiro life cycle processor - > < bean id = "lifecycleBeanPostProcessor" class = ". Org. Apache Shiro. Spring. LifecycleBeanPostProcessor "/ > <! - level AOP approach permission check - > < bean class = "org. Springframework. AOP. Framework. Autoproxy. DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true" /> </bean> <! - open shiro annotations - > < bean class = ". Org. Apache shiro. Spring. Security. The interceptor. AuthorizationAttributeSourceAdvisor "> <property name="securityManager" ref="securityManager"/> </bean>Copy the code
Spring – shiro. XML source
<? The XML version = "1.0" encoding = "utf-8"? > <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd "> <! > <bean id=" UserRealm "> <bean id=" UserRealm" class="io.renren.shiro.UserRealm"/> <! -- Shiro uses the Session of the Servlet container by default. You can specify using Shiro's native Session via the sessionMode attribute --> <! <property name="sessionMode" value="native"/> --> <bean id="securityManager" --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm"/> </bean> <! The Shiro master filter itself is very powerful in that it supports the execution of any custom filter based on URL path expressions --> <! <bean ID ="shiroFilter" > <bean ID ="shiroFilter" > <bean ID ="shiroFilter" > class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <! -- Shiro's core security interface, this property is required --> <property name="securityManager" ref="securityManager"/> <! <property name="loginUrl" value="/login.html"/> <property name="loginUrl" value="/login.html"/> <! --> <property name="successUrl" value="/index.html"/> <! -- Connections displayed when a user accesses a resource that is not authorized for the user --> <! If you want to test this property more obviously, you can change its value, such as unauthor.jsp, and then log in with [xuan Jade] and go to /admin/ listuser.jsp and see the browser display unauthor.jsp --> <property name="unauthorizedUrl" value="/login.html" /> <! -- Shiro connection constraint configuration, i.e. filter chain definition --> <! - here to cooperate with me this article to understand the role of each filter even http://blog.csdn.net/jadyer/article/details/12172839 - > <! - value below the value of the first '/' on behalf of the path is relative to it. The getContextPath () value to -- > <! -- anon: The filter is empty and does nothing, where the * after the.do and.jsp is a parameter, such as login.jsp? Main this --> <! - authc: Page under the filter must be validated before they can visit, it is Shiro built-in an interceptor org.. Apache Shiro. Web. Filter. Authc. FormAuthenticationFilter - > < property name="filterChainDefinitions"> <value> /statics/**=anon /login.html=anon /sys/schedule.html=perms[sys:schedule:save] /sys/login=anon /captcha.jpg=anon /**=authc </value> </property> </bean> <! - Shiro life cycle processor - > < bean id = "lifecycleBeanPostProcessor" class = ". Org. Apache Shiro. Spring. LifecycleBeanPostProcessor "/ > <! - level AOP approach permission check - > < bean class = "org. Springframework. AOP. Framework. Autoproxy. DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true" /> </bean> <! - open shiro annotations - > < bean class = ". Org. Apache shiro. Spring. Security. The interceptor. AuthorizationAttributeSourceAdvisor "> <property name="securityManager" ref="securityManager"/> </bean> </beans>Copy the code
Shiro’s other permission filters and their uses
- Anon: org, apache shiro. Web. Filter. Authc. AnonymousFilter
/statics/**=anon: Requests beginning with statics can be accessed without permission
- Authc: org, apache shiro. Web. Filter. Authc. FormAuthenticationFilter
/**=authc: Indicates that all requests require authentication permission and are allowed only after the permission passes
AuthcBasic: org, apache shiro. Web. Filter. Authc. BasicHttpAuthenticationFilter
/admins/user/**=authcBasic: Indicates not authenticated by HttpBasic
Perms: org, apache shiro. Web. Filter. Authz. PermissionsAuthorizationFilter
/admins/user/**=perms[user:add:*] : /admins/user/.. The “use:add:*” request must be accessed by the “use:add:*” permission, otherwise the login page will be redirected.
-
port : org.apache.shiro.web.filter.authz.PortFilter
* * = / admins/user/port [8081] : when request access port is not 8001, shiro will redirect to schemal: / / serverName: 8081? The queryString request. The schemal in this request is HTTP or HTTPS,serverName is the domain name in our original request, 8081 is the port number set in our port, and queryString is the parameter we carried in our original request.
- rest :org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
/admins/user/**=rest[user] : Rest indicates the request method. Equivalent to perms[user:method], where method is worth post, get, delete.
-
roles :org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
/admins/user/**=roles[admin] /admins/user/**=roles[admin] /admins/user/**=roles[admin] /admins/user/**=roles[admin]
-
ssl : org.apache.shiro.web.filter.authz.SslFilter
/admins/user/**= SSL: Indicates that the request is a security request and the protocol is HTTPS
- User: org, apache shiro. Web. Filter. Authc. UserFilter
/admins/user/**=user indicates that the user must exist. The login is not checked because the user does not exist at the time of login.
-
logout : org.apache.shiro.web.filter.authc.LogoutFilter
/admins/user/**=logout: Indicates that the request is an exit operation