Spring MVC + Shiro for permission validation

Source: Internet
Author: User



MAVEN's Pom.xml introduces Shiro (Spring Mvc+mybatis See the previous chapter).


<dependency>    <groupId>org.apache.shiro</groupId>    <artifactid>shiro-spring</ artifactid>    <version>1.2.5</version></dependency><!--http://mvnrepository.com/ Artifact/org.apache.shiro/shiro-ehcache--><dependency>    <groupid>org.apache.shiro</ groupid>    <artifactId>shiro-ehcache</artifactId>    <version>1.2.5</version> </dependency><dependency>    <groupId>org.apache.shiro</groupId>    <artifactid >shiro-core</artifactId>    <version>1.2.5</version></dependency><!--/http Mvnrepository.com/artifact/org.apache.shiro/shiro-web--><dependency>    <groupId> org.apache.shiro</groupid>    <artifactId>shiro-web</artifactId>    <version>1.2.5 </version></dependency>


Add Shiro filter in Web. xml

   <!--Configure the Shiro filter to let the Shiro filter system receive the request first--  <!--here filter-name must correspond to <bean id= defined in Applicationcontext.xml " Shirofilter "/>-  <!--use [/*] to match all requests, ensuring that all controllable requests are Shiro filtered-  <!-- This filter-mapping is usually placed at the front (that is, in front of the other filter-mapping) to ensure it is the first function in the filter chain--  <filter>      <filter-name >shiroFilter</filter-name>      <filter-class> org.springframework.web.filter.delegatingfilterproxy</filter-class>      <init-param>      <!-- The value defaults to False, which indicates that the life cycle is managed by Springapplicationcontext and set to True to be managed by Servletcontainer      <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>    



Add the Shiro configuration to the Spring configuration file

<!--Shiro Config--<!--inherit custom realm from Authorizingrealm, that is, specify Shiro to verify that the user is logged on as a custom Shirodbrealm.java--< Bean id= "Myrealm" class= "Com.blog.shiro.entity.BaseRealm"/> <!--Shiro The session of the servlet container is used by default, The SessionMode property allows you to specify the use of Shiro native session--<!--that is <property name= "SessionMode" value= "native"/&gt, detailed instructions in the official documentation-- > <!--This is mainly about setting up a custom single realm app, if you have more than one realm, you can use the ' Realms ' attribute instead--<bean id= "SecurityManager" class= "    Org.apache.shiro.web.mgt.DefaultWebSecurityManager "> <property name=" Realm "ref=" Myrealm "/> </bean> <!--Shiro Main filter itself is very powerful, its strength is that it supports any URL path expression-based, custom filter execution--<!--Web applications, Shiro controllable Web requests must be blocked by the Shiro main filter , Shiro provides the perfect support for spring-based Web applications--<bean id= "Shirofilter" class= " Org.apache.shiro.spring.web.ShiroFilterFactoryBean "> <!--Shiro's core security interface, this property is required--<property name=" SecurityManager "ref=" SecurityManager "/> <!--require a login link (can be replaced according to the URL of the project), non-required properties, by default automatically find"/login.jsp "under the Web project root directory Page--> <property name= "loginurl" value= "/company/admin/login.html"/> <!--the connection to jump after successful login (this property is not used in this example because the login succeeds      Logic in Logincontroller hard coded to main.jsp)-<!--<property name= "Successurl" value= "/system/main"/>-- <!--the user accesses a resource that is not authorized, the connection that is displayed-<!--if you want to test this property more clearly, you can modify its value, such as unauthor.jsp, and then use [Jade] login to access/admin/listuser.jsp to see the browser will display unauthor.jsp--<property name= "Unauthorizedurl" value= "/admin/index.html"/> <!--Shiro connection constraint configuration, which is Filter chain definition-<!--here to work with this article to understand the effects of each filter connection http://blog.csdn.net/jadyer/article/details/12172839--<!-- The first '/' of the Polygon value value represents the path relative to the value of Httpservletrequest.getcontextpath ()-<!--anon: it corresponds to the filter inside is empty, nothing is done, Here the. Do and. JSP * represents parameters, such as Login.jsp?main <!--authc: The page under the filter must be validated before it can be accessed. It is a shiro built-in interceptor org.apache.shiro.web.filter.authc.FormAuthenticationFilter---<property name= "Filters" > <map> <entry key= "permission" > <bean class= "Com.blog.shiro.filters.RoleAuthorizationFilter "> </bean> </entry> </map> </p roperty> <property name= "filterchaindefinitions" > <value> <! --/admin/login=anon/mydemo/login=anon/mydemo/getverifycodeimage=anon/main**=             Authc/user/info**=authc/admin/listuser**=authc,perms[admin:manage]- /admin/**=permission </value> </property></bean> <!--guarantees the realization of Shiro within The lifecycle function bean executes--<bean id= "Lifecyclebeanpostprocessor" class= " Org.apache.shiro.spring.LifecycleBeanPostProcessor "/> <!--open Shiro annotations (such as @requiresroles, @RequiresPermissions ), use SPRINGAOP to scan classes using Shiro annotations and secure logic verification if necessary-<!--Configure the following two beans--<!--enable Shiro Annotations for S pring-configured beans. Only run after the Lifecyclebeanprocessor have run--&Gt <!--because the Shiro annotations are not used in this example, comment out the two beans (the person feels that the permissions are hardcoded in the program by way of annotations, it is not very convenient to view them, it is not necessary to use them)-<!--<bean class= " Org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator "depends-on=" Lifecyclebeanpostprocessor "/> <bean class=" Org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor "> <property name="         SecurityManager "ref=" SecurityManager "/> </bean>-

Note: The above Com.blog.shiro.entity.BaseRealm belongs to your own custom authorization for the login user. Com.blog.shiro.filters.RoleAuthorizationFilter is the Shiro filter of its own definition for authorization verification. Filterchaindefinitions is used to specify the use of Shiro's default filter and custom filter to specifically notice the URL to intercept.

Below is a section of code that shows you a simple user login permission verification. The login page will not be posted.

The first is the handling of the login:
@RequestMapping (value={"/admin/login"},method={requestmethod.post}) Public String login (string username,string Password, Modelmap model) {if (Checker.isempty (username) | | Checker.isempty (password)) {model.put ("mesage", "Login failed: Please check your username and password!") ");} map<string, object> map = new hashmap<string,object> (); Map.put ("username", username); list<user> users = Userdaoimpl.findlistby (map), if (users.size () > 0) {User user = Users.get (0); if ( User.getpassword (). Equals (password)) {//from securityutils Subject Subject Subject = Securityutils.getsubject ();// Create Tokenusernamepasswordtoken token = new Usernamepasswordtoken (User.getusername (), User.getpassword ());// Sign in Subject.login (token) with token; return  "redirect:/admin/index.html";} Else{model.put ("Mesage", "Login failed: Please check your username and password!") ");}} Else{model.put ("Mesage", "Login failed: Please check your username and password!") ");} return "Login";}


The realization of Baserealm.java


Package Com.blog.shiro.entity;import Org.apache.commons.lang.builder.reflectiontostringbuilder;import Org.apache.commons.lang.builder.tostringstyle;import Org.apache.shiro.securityutils;import Org.apache.shiro.authc.authenticationexception;import Org.apache.shiro.authc.authenticationinfo;import Org.apache.shiro.authc.authenticationtoken;import Org.apache.shiro.authc.simpleauthenticationinfo;import Org.apache.shiro.authc.usernamepasswordtoken;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;public class Baserealm extends Authorizingrealm {/** * Grant roles and permissions for the currently logged on subject * @see tested: In this case, the call time for the method is required when the authorization resource is accessed * @see tested: The logic in the method is executed each time access is required to authorize the resource, which indicates that Authorizationcache is not enabled by default in this example * @see personal feeling With the Concurrentmapcache support that Spring3.1 started with, you have the flexibility to decide whether to enable AuthorizationcAche * @see For example, when obtaining permission information from a database, first go to the cache provided by Spring3.1 instead of using the Authorizationcache */@Override protected provided by Shior Authorizationinfo Dogetauthorizationinfo (principalcollection principals) {//Get the user name of the current login, equivalent to (String) Principals.fro Mrealm (This.getname ()). Iterator (). Next () String currentusername = (String) super.getavailableprincipal (principals)  ;  list<string> rolelist = new arraylist<string> ();  list<string> permissionlist = new arraylist<string> ();  Gets the details of the currently logged-on user from the database/\ User user = Userservice.getbyusername (currentusername); if (null! = user) {/////entity class User contains entity class information for user roles//if (Null!=user.getroles () && User.getro                  Les (). Size () >0) {////Get the role of the currently logged on user//for (role Role:user.getRoles ()) {//  Rolelist.add (Role.getname ()); Entity class role contains entity class information with role permissions//if (Null!=role.getpermissions () && role.geTpermissions (). Size () >0) {////Get permission//for (Permission Pmss:role.getPermis Sions ()) {//if (!  Stringutils.isempty (Pmss.getpermission ())) {//Permissionlist.add (Pmss.getpermission ());      //                          }  //                      }  //                  }  //              }  //          }  //  }else{//throw new Authorizationexception ();  }///Set roles and permissions for current user//Simpleauthorizationinfo simpleauthorinfo = new Simpleauthorizationinfo ();  Simpleauthorinfo.addroles (rolelist);          Simpleauthorinfo.addstringpermissions (permissionlist);          Simpleauthorizationinfo simpleauthorinfo = new Simpleauthorizationinfo ();            In practice, the System.out.println ("_________________________" +currentusername) may be obtained from the database as noted above; Adding a role, rather than adding it in a configuration sense, proves that the user has the Admin role//Add permission Simpleauthorinfo.addstringpeRmission ("/admin/index.html");              Simpleauthorinfo.addstringpermission ("/admin/left.html");              Simpleauthorinfo.addstringpermission ("/admin/info.html");              Simpleauthorinfo.addstringpermission ("/admin/user/list.html");              System.out.println ("the [admin] role and [admin:manage] permissions have been given to the user [Mike]");          return simpleauthorinfo; If the method does not do anything directly return NULL, it will cause any user access to the/admin/listuser.jsp will automatically jump to the address specified by Unauthorizedurl//See Applicationcontext.xml in the <bean id= "Shirofilter" > configuration}/** * Verify the current login subject * @see tested: In this case, the method is called Logincontrolle The R.login () method executes Subject.login () when */@Override protected authenticationinfo dogetauthenticationinfo (Authentica Tiontoken Authctoken) throws Authenticationexception {//Get tokens based on user name and password//actually this authctoken is from Logincontrolle R inside the Currentuser.login (token)//two tokens quoted are the same Usernamepasswordtoken token = (Usernamepasswordtoken) aut          Hctoken; SysteM.out.println ("Get to token when validating current subject" + reflectiontostringbuilder.tostring (token, Tostringstyle.multi_line_style)  );  User user = Userservice.getbyusername (token.getusername ()); if (null! = user) {//AuthenticationInfo Authcinfo = new Simpleauthenticationinfo (User.getusername (), use  R.getpassword (), User.getnickname ());  This.setsession ("CurrentUser", user);  return authcinfo;  }else{//return null; }//There is no need for comparison, the logic of Shiro will do, we only need to return a token related to the correct authentication information//white is the first parameter to fill in the login user name, the second parameter is filled with a valid login password (can be taken from the database, in this case in order to The demo is hard coded)//This way, only the user and password specified here can be verified authenticationinfo authcinfo = new simpleauthentication on the subsequent login page              Info (Token.getusername (), Token.getusername (), This.getname ());              This.setsession ("CurrentUser", Token.getusername ());          return authcinfo; A Unknownaccountexception exception is thrown in Logincontroller when no Simpleauthenticationinfo object is returned for the login user name}/** * Put some data into the shirosession, so that it can be used elsewhere * @see such as controller, using the direct use of Httpsession.getattribute (key) will be able to take the */PR          ivate void Setsession (Object key, Object value) {Subject CurrentUser = Securityutils.getsubject ();              if (null! = CurrentUser) {Session session = Currentuser.getsession ();              SYSTEM.OUT.PRINTLN ("Session default time-out is [" + session.gettimeout () + "] milliseconds");              if (null! = session) {Session.setattribute (key, value); }          }      }  }

Note: I'm using URIs here to manage permissions, which meanssimpleauthorinfo.addstringpermission ("/admin/index.html");
Simpleauthorinfo.addstringpermission ("/admin/left.html");
Simpleauthorinfo.addstringpermission ("/admin/info.html");
Simpleauthorinfo.addstringpermission ("/admin/user/list.html");This part of the code is authorized to verify that successful users have access to these URIs without the right to access other URIs, the following filter will be based on this authorization to open the URI to the user,authorization is required based on the database. There will be time to write a separate chapter on the implementation of the general authorization.

The code implementation of the custom filter:

Package Com.blog.shiro.filters;import Javax.servlet.servletrequest;import Javax.servlet.servletresponse;import Javax.servlet.http.httpservletrequest;import Org.apache.shiro.subject.subject;import Org.apache.shiro.web.filter.authz.authorizationfilter;public class Roleauthorizationfilter extends Authorizationfilter {@Overrideprotected Boolean isaccessallowed (servletrequest request,servletresponse response, Object object) throws Exception {//Gets the requested resource (that is, the requested URI) HttpServletRequest Httpreq = (httpservletrequest) request; String uri = Httpreq.getrequesturi ();//Gets the logged-on subject object based on the request response. Subject Subject = getsubject (request, response);//Determine if the logged on user has this right return subject.ispermitted (URI);}}




Shiro is simple and convenient to use, please leave a message if you have any questions.

Purely personal note form, if there is a mistake please leave a message to point out.


Spring MVC + Shiro for permission validation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.