Applying Apache Shiro in a Web project

Source: Internet
Author: User
Tags cas apache camel

Apache Shiro is a powerful and easy-to-integrate open-source rights framework that enables authentication, authorization, encryption, session management, and more. Authentication and authorization are the core of authority control, simply, "certification" is to prove who you are? The general practice of WEB applications is to submit user names and passwords through forms for authentication purposes. Authorization allows authenticated users to access protected resources. About Shiro a series of features and advantages, many articles have been enumerated, here no longer repeat, this article focuses on how to implement the Shiro in the Web Application authentication code authentication and how to achieve single sign-on.

User Rights model

Before we uncover the Shiro veil, we need to recognize the user rights model. The user rights model mentioned in this paper refers to the data model used to express user information and user's permission information. Can prove "Who are you?" "," How many protected resources can you access? ”。 In order to achieve a more flexible user rights data model, the user information is usually represented by a single entity, and the user rights information is represented by two entities.

    1. User information with Loginaccount, the simplest user information may contain only the user name LoginName and password password two attributes. The actual application may contain information such as whether the user is disabled, whether the user information expires, and so on.
    2. User rights information with role and Permission, role and Permission form a many-to-many relationship. Permission can be understood as an operation on a resource, Role can be simply understood as a collection of Permission.
    3. Many-to-many relationships are formed between user information and Role. Indicates that the same user can have multiple role, and a role can be owned by multiple users.
Figure 1. User Rights model

Authentication and authorization Shiro authentication and authorization process
    • Resources that are protected by Shiro are certified and authorized. Use Shiro to protect URLs see the "Integration with Spring" section.
    • A user accesses a URL protected by Shiro, such as http://host/security/action.do.
    • Shiro first check whether the user has passed the certification, if not pass the authentication check, then jump to the login page, otherwise authorization check. The certification process requires the use of realm to obtain user and password information, typically we implement the JDBC Realm, where the information required for user authentication is obtained from the database. If the cache is used, the user information is obtained from the cache except for the first time.
    • After the certification is accepted Shiro authorization check, authorization check also need to get user rights information through Realm. The user rights information required by Shiro includes Role or Permission, which can be either or both, depending on the configuration of the protected resource. If the user rights information does not contain the Role or Permission required by Shiro, authorization does not pass. The resource corresponding to the protected URL can be accessed only by authorization, otherwise jump to an unauthorized page.
Shiro Realm

In the Shiro certification and authorization process, the reference to Realm. Realm can be understood as a DAO that reads user information, roles, and permissions. Because most WEB applications use relational databases, it is common practice to implement JDBC realm, which later mentions the implementation of CAS realm and another realm.

Listing 1. Implement your own JDBC Realm
 public class Myshirorealm extends authorizingrealm{//business interface for obtaining user information and user rights information private Businessmanager Businessmanag        Er Get authorization information protected Authorizationinfo Dogetauthorizationinfo (principalcollection principals) {String Usern             Ame = (String) Principals.fromrealm (GetName ()). Iterator (). Next (); if (username! = null) {//query user authorization Information collection<string> pers=businessmanager.querypermissions (username)          ;             if (pers! = null &&!pers.isempty ()) {Simpleauthorizationinfo info = new Simpleauthorizationinfo ();                         for (String each:pers) info.addstringpermissions (each);          return info;    }} return null; }//Get authentication information protected AuthenticationInfo dogetauthenticationinfo (Authenticationtoken authctoken) throws Au       thenticationexception {Usernamepasswordtoken token = (usernamepasswordtoken) Authctoken; Receive via FormThe user name String username = token.getusername (); if (username! = NULL &&! "".                   Equals (username)) {Loginaccount account = Businessmanager.get (username); if (account! = null) {return new Simpleauthenticationinfo (Account.getloginname (), ACCOUNT.GETP          Assword (), GetName ());    }} return null; }  }

Code Description:

    1. Businessmanager represents a business class that obtains user information and user rights information from a database, and the actual situation may vary depending on the user rights model design or the persistence framework, and no sample code is presented here.
    2. Dogetauthenticationinfo method, fetch user information. In contrast to the user rights model, the Loginaccount entity is taken. Eventually we need to provide AuthenticationInfo objects for Shiro.
    3. Dogetauthorizationinfo method to obtain user rights information. The code gives an example of getting the user Permission, similar to the code that gets the user Role. The user rights information provided for Shiro is returned as an Authorizationinfo object.

Why do you have a passion for Shiro?

Maybe someone has to ask, I have been using spring, the security components of the application have already chosen spring security, why need Shiro? Of course, it is undeniable that Spring security is also an excellent safety control component. The purpose of this article is not to allow you to choose Shiro and to abandon Spring Security in an objective manner, with a slight comparison between the two:

    1. Simplicity, Shiro is easier to use than Spring Security and easier to understand.
    2. Flexibility, Shiro can run in any application environment, such as Web, EJB, IoC, Google app Engine, without relying on these environments. Spring Security can only be used with spring integration.
    3. Pluggable, Shiro clean APIs and design patterns make it easy to integrate with many other frameworks and applications. Shiro can be seamlessly integrated with third-party frameworks such as Spring, Grails, Wicket, Tapestry, Mule, Apache Camel, and Vaadin. Spring Security seems to be catching geumcheon in this respect.

Integration with Spring

Spring is widely used in Java WEB application development, and it can be said that spring is the mainstream in comparison with EJBS. Shiro itself provides good support for spring, and it's easy to integrate spring into your application.

With the user rights data model mentioned earlier, and the implementation of your Realm, we can begin to integrate Shiro for the application service.

Installation of Shiro

Shiro installation is very simple, in the Shiro official website download Shiro-all-1.2.0.jar, Shiro-cas-1.2.0.jar (Single sign-on needs), and slf4j website download Shiro rely on the log components Slf4j-api-1.6.1.jar. Spring-related JAR packages are not listed here. These JAR packages need to be placed in the Web Engineering/web-inf/lib/directory. At this point, the rest is configured.

Configure filters

First, configuring the filter allows the requested resource to undergo Shiro filtering, similar to the use of other filters.

Listing 2. Web. XML configuration
<filter>    <filter-name>shiroFilter</filter-name>    <filter-class>       Org.springframework.web.filter.DelegatingFilterProxy    </filter-class>  </filter>  < filter-mapping>    <filter-name>shiroFilter</filter-name>    <url-pattern>/*</ Url-pattern>  </filter-mapping>
Spring Configuration

Next, just configure a series of beans managed by the Spring container, and the integration is done. The function of each Bean is shown in the code description.

Listing 3. Spring Configuration
 <bean id= "Shirofilter" class= "Org.apache.shiro.spring.web.ShiroFilterFactoryBean" > <property name= " SecurityManager "ref=" SecurityManager "/> <property name=" loginurl "value="/login.do "/> <property name=" s Uccessurl "value="/welcome.do "/> <property name=" Unauthorizedurl "value="/403.do "/> <property name=" filt ERs "> <util:map> <entry key=" authc "value-ref=" Formauthenticationfilter "/> </util:m          ap> </property> <property name= "filterchaindefinitions" > <value>/=anon /login.do*=authc/logout.do*=anon # Permission Configuration Example/security/account/view.do=authc,perms[secur Ity_account_view]/** = authc </value> </property> </bean> <bean id= "sec Uritymanager "class=" Org.apache.shiro.web.mgt.DefaultWebSecurityManager "> <property name=" Realm "ref=" Myshirorealm "/> </bean> <bean id= "Myshirorealm" class= "Xxx.packagename.MyShiroRealm" > <!--businessmanager to implement user name password query--<propert Y name= "Businessmanager" ref= "Businessmanager"/> <property name= "CacheManager" ref= "ShiroCacheManager"/> & lt;/bean> <bean id= "lifecyclebeanpostprocessor" class= "Org.apache.shiro.spring.LifecycleBeanPostProcessor"/ > <bean id= "Shirocachemanager" class= "Org.apache.shiro.cache.ehcache.EhCacheManager" > <property name= "c Achemanager "ref=" CacheManager "/> </bean> <bean id=" Formauthenticationfilter "class=" Org.apache.shiro.web.filter.authc.FormAuthenticationFilter "/>

Code Description:

    1. Shirofilter loginurl for the login page address, Successurl for the Login Success page address (if the first access to the protected URL login successful, then jump to the actual access page), Unauthorizedurl authentication failed to access the page (mentioned earlier " Unauthorized pages ").
    2. The filters property in Shirofilter, Formauthenticationfilter is configured as a filter based on forms authentication.
    3. Filterchaindefinitions attribute in Shirofilter, anon means anonymous access (no authentication and authorization required), AUTHC means authentication required, Perms[security_account_view] means the user needs to provide a value of " Security_account_view "Permission information. This shows that the connection address is configured as AUTHC or perms[xxx] as a protected resource.
    4. SecurityManager Realm attribute, configured for our own implementation of realm. For realm, see the "Shiro Realm" section above.
    5. Myshirorealm is the Realm class we need to implement, and in order to reduce the database pressure, we add a caching mechanism.
    6. Shirocachemanager is the Shiro configuration of the cache framework EhCache.

Implement Verification Code authentication

Verification codes are a means of effectively preventing brute force, and the common practice is to generate a string of random strings on the server that are associated with the current user session (which we usually put into session) and then show the end user A picture that has been "disturbed". The next step is allowed only if the user enters the same content as the server produces.

Generate Verification Code

As a demonstration, we chose the Open source verification code component Kaptcha. In this way, we simply configure a Servlet, and the page can display the graphical verification code via the IMG tag.

Listing 4. Web. XML configuration
<!--captcha servlet-->  <servlet>    <servlet-name>kaptcha</servlet-name>    < servlet-class>       com.google.code.kaptcha.servlet.KaptchaServlet    </servlet-class>  </ servlet>  <servlet-mapping>  <servlet-name>kaptcha</servlet-name>  < Url-pattern>/images/kaptcha.jpg</url-pattern>  </servlet-mapping>
Extended Usernamepasswordtoken

Shiro form authentication, page submitted user name password and other information, with the Usernamepasswordtoken class to receive, it is easy to think, to receive the page verification code input, we need to expand this class:

Listing 5. Captchausernamepasswordtoken
public class Captchausernamepasswordtoken extends usernamepasswordtoken{  private String captcha;  Omit getter and Setter methods public Captchausernamepasswordtoken (String username, char[] password,  boolean rememberme, St Ring host,string captcha) {  super (username, password, rememberme, host);  This.captcha = Captcha;  }  }
Extended Formauthenticationfilter

Next we extend the Formauthenticationfilter class, overriding the Createtoken method first to obtain the Captchausernamepasswordtoken instance, and then add the validation code to validate the method Docaptchavalidate; Finally, the authentication method covering Shiro is Executelogin, and the verification code is verified before the original form authentication logic processing.

Listing 6. Captchausernamepasswordtoken
 public class Captchaformauthenticationfilter extends formauthenticationfilter{public static final String default_capt       Cha_param = "Captcha";       Private String Captchaparam = Default_captcha_param;    Public String Getcaptchaparam () {return captchaparam;    } public void Setcaptchaparam (String captchaparam) {this.captchaparam = Captchaparam; } protected String Getcaptcha (ServletRequest request) {return Webutils.getcleanparam (request, Getcaptchaparam    ()); }//Create Token protected Captchausernamepasswordtoken Createtoken (ServletRequest request, Servletresponse R       Esponse) {String username = getusername (request);       String Password = getpassword (request);       String captcha = Getcaptcha (request);       Boolean rememberme = Isrememberme (request);                          String host = gethost (request);    return new Captchausernamepasswordtoken (username, password, rememberme, Host,captcha); }       //Verification Code Check protected void Docaptchavalidate (HttpServletRequest request, Captchausernamepasswordtoken token) { String captcha = (string) request.getsession (). getattribute (Com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY             ); if (Captcha!=null &&!captcha.equalsignorecase (Token.getcaptcha ())) {throw new Incorrectcaptcha Exception ("Captcha Error!       "); }}//Authentication protected Boolean Executelogin (ServletRequest request, servletresponse response) throws Except              Ion {Captchausernamepasswordtoken token = Createtoken (request, response);                           try {docaptchavalidate (httpservletrequest) request,token);          Subject Subject = getsubject (request, response);                               Subject.login (token);       Return onloginsuccess (token, subject, request, response);      } catch (Authenticationexception e) {return onloginfailure (token, E, request, response); }    }  } 

Code Description:

    1. Add the Captchaparam variable so that the parameter name of the page form submission verification code can be flexibly configured.
    2. In the Docaptchavalidate method, the Authenticode checksum uses the API provided by the framework Kaptcha.
Add Incorrectcaptchaexception

The previous verification code check does not pass, we throw an exception incorrectcaptchaexception, this class inherits authenticationexception, it is necessary to extend a new exception class, so that the page can be more accurate display error message.

Listing 7. Incorrectcaptchaexception
public class Incorrectcaptchaexception extends authenticationexception{public       incorrectcaptchaexception () {       super ();    }       Public incorrectcaptchaexception (String message, throwable cause) {       Super (message, cause);    }       Public incorrectcaptchaexception (String message) {       super (message);    }       Public incorrectcaptchaexception (Throwable cause) {       super (cause);    }  }
The page shows the CAPTCHA error message listing 8. Page Authentication error message display
Object Obj=request.getattribute (    org.apache.shiro.web.filter.authc.FormAuthenticationFilter       . Default_error_key_attribute_name);  Authenticationexception authexp = (authenticationexception) obj;  if (authexp! = null) {    String expmsg= "";       if (authexp instanceof unknownaccountexception | |       Authexp instanceof incorrectcredentialsexception) {       expmsg= "wrong user account or password! ";    } else if (authexp instanceof incorrectcaptchaexception) {       expmsg= ' captcha Error! ";    } else{       expmsg= "Login exception:" +authexp.getmessage ();    }        Out.print ("<div class=\" error\ ">" +expmsg+ "</div>");  }

Implement single Sign-on

In the previous chapters, we recognized Shiro's certification and authorization and integrated it with Spring. In reality, there is such a scenario, we have a lot of business systems, according to the previous ideas, if access to each business system, to be certified, so it is a bit difficult to accepting people. Is there a mechanism that allows us to access the target system without having to authenticate once?

The above scenario is the single sign-on SSO that we often mention. Shiro support for CAS starting from version 1.2, CAS is an implementation of single sign-on.

Shiro CAS Certification Process
    • The first time a user accesses a protected resource, such as Http://casclient/security/view.do
    • The Shiro first caches the request address (http://casclient/security/view.do) because it has not passed the authentication.
    • It then jumps to the CAS server for login authentication and needs to be returned to the requesting CAS client upon completion of the CAS service-side authentication, so the return address (called CAS Service in Shiro) must be added to the parameter upon request. such as Http://casserver/login?service=http://casclient/shiro-cas
    • After the CAS server is authenticated, the CAS server adds ticket for the return address. such as Http://casclient/shiro-cas?ticket=ST-4-BWMEnXfpxfVD2jrkVaLl-cas
    • Next, Shiro verifies that the ticket is valid. Because CAS clients do not provide direct authentication, Shiro will initiate ticket check checks to the CAS server, and only if the server returns success, Shiro will consider the authentication passed.
    • Certification passed, enter authorization check. The Shiro authorization check is the same as mentioned earlier.
    • The final authorization check passes, the user normally accesses to http://casclient/security/view.do.
CAS Realm

Shiro provides a class named Casrealm, similar to the previously mentioned JDBC Realm, which also includes both authentication and authorization functions. Authentication is the validation of whether the ticket returned from the CAS server is valid, or the authorization to obtain user rights information.

To implement the single sign-on feature, you need to extend the Casrealm class.

Listing 9. Shiro CAS Realm
public class Mycasrealm extends casrealm{       //Get authorization information   protected Authorizationinfo dogetauthorizationinfo (       PrincipalCollection principals) {       //... Same as previous Myshirorealm   } public        String Getcasserverurlprefix () {       return "Http://casserver/login";    }       Public String Getcasservice () {       return "Http://casclient/shiro-cas";    }    +  }

Code Description:

    1. Dogetauthorizationinfo Obtaining authorization information is the same as in the previous section, "Implementing your own JDBC Realm."
    2. The authentication function is implemented by the Casrealm provided by Shiro itself.
    3. The Getcasserverurlprefix method returns the CAS server address, which is typically configured by using parameters.
    4. The Getcasservice method returns the CAS client processing address, which is typically configured by using parameters.
    5. The authentication process needs to be keystore, otherwise an exception will occur. Can be specified by setting the system properties, such as System.setproperty ("Javax.net.ssl.trustStore", "keystore-file");
CAS Spring Configuration

The Spring configuration that implements single sign-on is similar to the previous one, and differs from the code description.

Listing 10. Shiro CAS Spring Configuration
 <bean id= "Shirofilter" class= "Org.apache.shiro.spring.web.ShiroFilterFactoryBean" > <property name= "Securi Tymanager "ref=" SecurityManager "/> <property name=" loginurl "value=" http://casserver/login?service=http://c Asclient/shiro-cas "/> <property name=" Successurl "value="/welcome.do "/> <property name=" UnauthorizedUrl "Value="/403.do "/> <property name=" Filters "> <util:map> <entry key=" AUTHC "value-ref= "Formauthenticationfilter"/> <entry key= "cas" value-ref= "Casfilter"/> </util:map> </pr operty> <property name= "filterchaindefinitions" > <value>/shiro-cas*=cas/logout . Do*=anon/casticketerror.do*=anon # Permission Configuration Example/security/account/view.do=authc,perms[secu Rity_account_view]/** = authc </value> </property> </bean> <bean id= " SecurityManager "class="Org.apache.shiro.web.mgt.DefaultWebSecurityManager" > <property name= "Realm" ref= "Myshirorealm"/> </  bean> <bean id= "lifecyclebeanpostprocessor" class= "Org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!--CAS Realm--<bean id= "Myshirorealm" class= "Xxx.packagename.MyCasRealm" > <property name= "Cacheman Ager "ref=" Shirocachemanager "/> </bean> <bean id=" Shirocachemanager "class=" Org.apache.shiro.cache.ehcache.EhCacheManager "> <property name=" CacheManager "ref=" CacheManager "/> </ bean> <bean id= "Formauthenticationfilter" class= "Org.apache.shiro.web.filter.authc.FormAuthenticationFilter "/> <!--CAS Filter--<bean id=" Casfilter "class=" Org.apache.shiro.cas.CasFilter "> <property name = "Failureurl" value= "casticketerror.do"/> </bean>

Code Description:

    1. Shirofilter in the Loginurl property, the service-side address of the login CAS, and the parameter service is the return address of the server.
    2. Myshirorealm is the CAS Realm mentioned in the previous section.
    3. The Failureurl property in Casfilter is the error page that is displayed when the Ticket check fails.

Summarize

At this point, we have a more in-depth understanding of Shiro. Shiro flexible, powerful, almost meet our actual application of all kinds of situations, but also what? Let me start using Shiro to escort the app!

Applying Apache Shiro in a Web project

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.