Custom realm of "Shiro" Apache Shiro architecture

Source: Internet
Author: User

Previously written in the blog is to use the. ini file to obtain information, including user information, role information, permissions information and so on. When entering the system, it is accessed from the. ini file. In practice, unless the system is particularly simple, it is generally not the case, this information needs to be maintained in the database, so you need to use a custom realm.

Written in front: this blog post was modified on the basis of the previous Shiro integrated Web.

1. Database Building Tables

First in the database to create a new three tables: T_user,t_role and T_permission, respectively, store user information, role information and permissions information, the following statements are built:

CREATE TABLE ' T_role '(' id ' int( One) not NULLAuto_increment COMMENT' primary key ',' RoleName ' varchar( -)DEFAULT NULLCOMMENT' role name ',PRIMARY KEY(' id ')) Engine=innodb auto_increment=4 DEFAULTCharset=utf8CREATE TABLE ' T_user '(' id ' int( One) not NULLAuto_increment COMMENT' User primary key ',' username ' varchar( -) not NULLCOMMENT' User name ',' Password ' varchar( -) not NULLCOMMENT' Password ',' role_id ' int( One)DEFAULT NULLCOMMENT' Foreign Key association role table ',PRIMARY KEY(' id '),KEY ' role_id '(' role_id '),CONSTRAINT ' T_user_ibfk_1 ' FOREIGN KEY(' role_id ')REFERENCES ' T_role '(' id ')) Engine=innodb auto_increment=4 DEFAULTCharset=utf8CREATE TABLE ' T_permission '(' id ' int( One) not NULLAuto_increment COMMENT' primary key ',' Permissionname ' varchar( -) not NULLCOMMENT' Permission name ',' role_id ' int( One)DEFAULT NULLCOMMENT' Foreign Key association role ',PRIMARY KEY(' id '),KEY ' role_id '(' role_id '),CONSTRAINT ' T_permission_ibfk_1 ' FOREIGN KEY(' role_id ')REFERENCES ' T_role '(' id ')) Engine=innodb auto_increment=3 DEFAULTCharset=utf8

I have added some test data in each table, as follows:

2. Custom Realm

Custom realms need to operate the database, all first have to write a DAO, using the original JDBC, mainly the following custom realm.

 Public  class Userdao {    //Find users by user name     PublicUserGetbyusername(Connection conn, String username)throwsException {User Resultuser =NULL; String sql ="SELECT * from T_user where username=?";        PreparedStatement PS = conn.preparestatement (SQL); Ps.setstring (1, username); ResultSet rs = Ps.executequery ();if(Rs.next ()) {Resultuser =NewUser (); Resultuser.setid (Rs.getint ("id")); Resultuser.setusername (Rs.getstring ("username")); Resultuser.setpassword (Rs.getstring ("Password")); }returnResultuser; }//Search for a user-owned role based on user name     PublicSet<string>GetRoles(Connection conn, String username)throwsException {set<string> roles =NewHashset<string> (); String sql ="SELECT * from T_user u, t_role r where U.role_id=r.id and u.username=?";        PreparedStatement PS = conn.preparestatement (SQL); Ps.setstring (1, username); ResultSet rs = Ps.executequery (); while(Rs.next ()) {Roles.add (rs.getstring ("RoleName")); }returnRoles }//Find the permissions that the user role has under the user name     PublicSet<string>getperms(Connection conn, String username)throwsException {set<string> perms =NewHashset<string> (); String sql ="SELECT * from T_user u, t_role r, T_permission p where u.role_id=r.id and P.role_id=r.id and u.username=?";        PreparedStatement PS = conn.preparestatement (SQL); Ps.setstring (1, username); ResultSet rs = Ps.executequery (); while(Rs.next ()) {Perms.add (rs.getstring ("Permissionname")); }returnPerms }}

With DAO, you can then write a custom realm, the custom realm needs to inherit the Authorizingrealm class, because the class encapsulates a lot of methods, it is a step-by-step inheritance from the Realm class, after inheriting the Authorizingrealm class, You need to rewrite two methods:

Dogetauthenticationinfo () Method: Used to verify the current logged on user, to obtain authentication information
Dogetauthorizationinfo () Method: Used to grant permissions and roles for the currently logged-on user (already logged in successfully)

Here's a look at the specific implementation:

 Public  class myrealm extends authorizingrealm {    PrivateUserdao Userdao =NewUserdao ();//grant permissions and roles for the currently logged on successful user, already logged in successfully    @Override    protectedAuthorizationinfoDogetauthorizationinfo(PrincipalCollection principals) {String username = (string) principals.getprimaryprincipal ();//Get user nameSimpleauthorizationinfo Authorizationinfo =NewSimpleauthorizationinfo (); Connection conn =NULL;Try{conn = dbutil.getconnection (); Authorizationinfo.setroles (Userdao.getroles (conn, username));//Set roleAuthorizationinfo.setstringpermissions (USERDAO.GETPERMS (conn, username));//Set permissions}Catch(Exception e) {//TODO auto-generated catch blockE.printstacktrace (); }finally{Try{dbutil.closeconnection (conn); }Catch(Exception e) {//TODO auto-generated catch blockE.printstacktrace (); }        }returnAuthorizationinfo; }//Verify the user who is currently logged in, get authentication information    @Override    protectedAuthenticationInfoDogetauthenticationinfo(Authenticationtoken token)throwsauthenticationexception {String username = (string) token.getprincipal ();//Get user nameConnection conn =NULL;Try{conn = dbutil.getconnection (); User user = Userdao.getbyusername (conn, username);//Only user information based on user name is identified, no password is involved            if(User! =NULL) {AuthenticationInfo Authcinfo =NewSimpleauthenticationinfo (User.getusername (), User.getpassword (),"Myrealm");returnAuthcinfo; }Else{return NULL; }        }Catch(Exception e) {//TODO auto-generated catch blockE.printstacktrace (); }finally{Try{dbutil.closeconnection (conn); }Catch(Exception e) {//TODO auto-generated catch blockE.printstacktrace (); }        }return NULL; }}

From the above two methods can be seen: Authentication is based on user input user name from the database to identify the user, the user name corresponding to this time does not involve a password, that is, even if the user entered the wrong password, it can be detected to the user, Then the user's correct information encapsulated in the Authcinfo returned to Shiro, the next thing is Shiro, it will be based on the real information and the user's foreground input user name and password to verify, this time also to verify the password, if the verification by let the user login, Otherwise, jump to the specified page. In the same vein, when authorization is granted, the role and permissions associated with the user name are obtained based on the user name, and then encapsulated in Authorizationinfo returned to Shiro.

3. Modifying the INI file

In this configuration file, [users] and [roles] information can be deleted, because this information is maintained from the database, in addition to the file to specify our custom realm fully qualified name, and specify SecurityManager realm to use our custom realm as follows:

[main]authc.loginUrl=/loginroles.unauthorizedUrl=/unauthorized.jspperms.unauthorizedUrl=/unauthorized.jsp#定义自己的realmmyRealm=demo.shiro.realm.MyRealmsecurityManager.realms=$myRealm#定义请求的地址需要做什么验证[urls]/login=anon /admin=authc /student=roles[teacher]/teacher=perms["user:create"]

So our custom realm is done, according to the configuration file, when we request .../admin will be authenticated, so it will enter the Loginservlet, when the call currentUser.login(token); , Will enter the Dogetauthenticationinfo method in our custom realm to initialize the identity and then hand it to Shiro to verify. When we ask .../student, we will authenticate first, that is the process above, and then verify the passage, when we request again .../student, Will enter the Dogetauthorizationinfo method in our custom realm to initialize the permission, and then give it to Shiro to verify.
In the next blog post I will summarize how to apply Shiro to real projects, that is, how to integrate Shiro into spring.

-Willing to share and progress together!
--My Blog home: http://blog.csdn.net/eson_15

"Shiro" Apache Shiro architecture Custom Realm

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.