1. Introduction
The Apache Shiro is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management.
certification, Authorization:
Authentication simply said, is the time to log in to determine whether your username and password exactly match, is to prove you are you.
Authorization is the grant of roles and permissions on the basis of authentication. Permissions determine what a user can do. roles, permissions:
Permissions define whether a user can perform an action.
A role is a set of permissions.
We usually bind a set of permissions to a role, and then assign one or more roles to a user, which enables control of the permissions. That is, the permission is defined to the user through the role. Role as a collection of permissions, to facilitate the management of our rights. 2. Implement simple login function add Shiro dependency
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactid>shiro-core</ artifactid>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${ junit.version}</version>
<scope>test</scope>
</dependency>
Configuration file Shiro.ini
[Users]
Heqianqian = 12345666
3. Write test code
public class Simplelogintest {
@Test public
void Test () throws Exception {
shiroutils.login ("Classpath: Shiro/shiro.ini "," Heqianqian "," 12345666 ");
}
public class Shiroutils {public static Subject Getsubject (String path) {Inisecuritymanagerfactory factory =
New Inisecuritymanagerfactory (path);
SecurityManager manager = Factory.getinstance ();
Securityutils.setsecuritymanager (manager);
return Securityutils.getsubject (); public static Subject login (string path, String userName, String passWord) {Subject Subject = Getsubject (P
ATH);
Usernamepasswordtoken token = new Usernamepasswordtoken (UserName, PassWord);
try {subject.login (token);
SYSTEM.OUT.PRINTLN ("Login Successful");
catch (Unknownaccountexception e) {System.out.println ("Invalid user name");
E.printstacktrace ();
catch (Incorrectcredentialsexception e) {System.out.println ("password error");
E.printstacktrace ();
catch (Authenticationexception e) {e.printstacktrace ();
}//subject.logout (); System.out. println ("exit success");
return subject;
}
}
Subject is the main body of our login, here is the equivalent of a bridge, all of our operations are actually through Subject to help us complete. SecurityManager similar to the Dispatcherservlet in spring MVC, which acts like a front-end controller Realm is a secure data source, we want to store information similar to user names and passwords in Realm, Shiro can help us finish into a series of operations such as authentication and authorization
In this case, Realm is called Inirealm.
3. Use of Jdbcrealm
In the previous example of the data written in the configuration file, we can also read data from the database to add dependencies
<dependency> <groupId>org.apache.shiro</groupId> <ARTIFACTID>SHIRO-CORE</ARTIFACTID&G
T <version>1.3.2</version> </dependency> <dependency> <groupId>c3p0</groupId> & Lt;artifactid>c3p0</artifactid> <version>0.9.1.2</version> </dependency> <
Dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <depende ncy> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>
;${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactid>slf4j-log4j12</aRtifactid> <version>${slf4j.version}</version> </dependency>
Write configuration file Jdbcrealm.ini
[Main]
# represents the class that instantiates the right string representation and assigns the variable to the left string representation.
# #JdbcRealm默认使用users表
jdbcrealm = Org.apache.shiro.realm.jdbc.JdbcRealm
DataSource = Com.mchange.v2.c3p0.ComboPooledDataSource
datasource.driverclass = com.mysql.jdbc.Driver
datasource.user = Root
Datasource.password = * * * * indicates that the
property value Jdbcurl is set on the DataSource variable, and this property value is a string.
Datasource.jdbcurl = Jdbc:mysql://localhost:3306/ssm?useunicode=true&characterencoding=utf-8
# indicates pair Jdbcrealm this variable to set the property value DataSource, the DataSource property is an object instantiated above, so that the object is to use the prefix ' $ '.
Jdbcrealm.datasource = $dataSource
Securitymanager.realms = $jdbcRealm
Database Build Table
DROP DATABASE Db_shiro;
# Creating database Db_shiro Create DB
db_shiro DEFAULT CHARACTER SET UTF8 COLLATE utf8_general_ci;
# using the database Db_shiro use
Db_shiro;
Drop table if exists users;
CREATE TABLE users (
ID int (one) not null auto_increment comment ' primary key ',
username varchar default NULL comment ' user Name ',
password varchar () default NULL comment ' password ',
PRIMARY KEY (ID)
) engine=innodb auto_increment=1 Default Charset=utf8 comment ' user table ';
Insert into users (Username,password) VALUES (' Hqq ', ' 123456 ');
Attention:
The table name that is built here is users because Jdbcrealm finds data in the Users table by default
Jdbcrealm Source
public class Jdbcrealm extends Authorizingrealm {
protected static final String default_authentication_query = "Selec T password from users where username =? ";
Protected static final String default_salted_authentication_query = "Select Password, password_salt from users where Usern ame =? ";
Protected static final String default_user_roles_query = "Select Role_name from user_roles where username =?";
Protected static final String default_permissions_query = "SELECT permission from roles_permissions where role_name =?";
...
}
4. Writing test methods
public class Jdbcrealmtest {
private String userName = "Heqianqian";
Private String PassWord = "123";
Private Logger Logger = Logger.getlogger (jdbcrealmtest.class);
@Test public
void Test () throws Exception {
shiroutils.login ("Classpath:shiro/jdbcrealm.ini", UserName, PassWord);
}
4. Custom Realm
Way One: Implements Realm
The Realm implemented in this way can only implement authentication operation, and can not implement authorization operation.
public class Maprealm implements Realm {private static map<string, string> users = new hashmap<> ();
static {Users.put ("Heqianqian", "123");
Users.put ("Lucy", "456"); /** * Returns a unique realm name */@Override public String getName () {System.out.println ("Set realm name"
);
Return to "my Maprealm";
/** * To determine whether to support token/@Override public boolean supports (Authenticationtoken Authenticationtoken) {
SYSTEM.OUT.PRINTLN ("The supported Token method in Map Realm");
Represents a Token return Authenticationtoken instanceof Usernamepasswordtoken that supports only usernamepasswordtoken types; /** * Obtain authentication information */@Override public authenticationinfo getauthenticationinfo (Authenticationtoken AUT
Henticationtoken) throws Authenticationexception {System.out.println ("method of returning authentication information in Map Realm");
String userName = (string) authenticationtoken.getprincipal (); String PassWord = new StRing ((char[]) authenticationtoken.getcredentials ());
if (!users.containskey (UserName)) {System.out.println ("username error!");
else if (!users.get (userName). Equals (PassWord)) {System.out.println ("Bad password!");
Return to New Simpleauthenticationinfo (UserName, PassWord, GetName ());
}
}
Write configuration file Maprealm.ini
[Main]
# declares our own definition of a Realm
Mymaprealm = Heqianqian.shiro.realm.MapRealm
# to inject our own defined Realm into the SecurityManager To Securitymanager.realms in sex
= $myMapRealm
Test
public class Maprealmtest {
@Test public
void Test () throws Exception {
Shiroutils.login ("classpath:shiro/ Maprealm.ini "," Heqianqian "," 123 ");
}
mode two: Extends Authorizingrealm (a more commonly used way, because this can be done to achieve the authentication operation, but also to implement the authorization operation)
public class Mystaticrealm extends Authorizingrealm {/** * for authorization */@Override
Protected Authorizationinfo Dogetauthorizationinfo (principalcollection principalcollection) {//temporarily ignored, introduced later
return null; /** * for certification/@Override protected AuthenticationInfo dogetauthenticationinfo (Authenticationtoken
Authenticationtoken) throws Authenticationexception {System.out.println ("Method of authentication in Static Realm");
String userName = Authenticationtoken.getprincipal (). toString ();
String password = new string ((char[)) authenticationtoken.getcredentials ()); if (!)
Heqianqian ". Equals (UserName)) {throw new Unknownaccountexception (" Invalid user name "); else if (!)
123 ". Equals (password)) {throw new incorrectcredentialsexception (" Invalid password ");
Return to New Simpleauthenticationinfo ("Heqianqian", "123", GetName ()); }
}
Write configuration file Mystaticrealm.ini
[Main]
Mystaticrealm = Heqianqian.shiro.realm.MyStaticRealm
Securitymanager.realms = $myStaticRealm
Test
@Test public
void Testpermission () throws Exception {
Subject Subject = Shiroutils.login ("classpath:shiro/ Mystaticrealm.ini "," Heqianqian "," 123 ");
}
knowledge Points: Configuring Authentication policies
At this time, we will have a question, SecurityManager's attribute since is realms, the description may set several Realm, their authentication order is how.
So for a number of Realm,shiro provides a way to configure, let us decide how many reaml in the case of simultaneous declaration, which Realm return authentication information, this is our authentication strategy.
The authentication strategy mainly has the following three kinds:
1,firstsuccessfulstrategy: As long as there is a Realm verification success, only return the first Realm authentication success of the authentication information, other neglect;
2,atleastonesuccessfulstrategy: (This is the default use of the authentication strategy, that is, in the case of Shiro to use the authentication strategy) as long as there is a Realm verification success, and Firstsuccessfulstrategy, returns the authentication information of all Realm authentication success;
3,allsuccessfulstrategy: All Realm verification success is successful, and return all Realm authentication successful authentication information, if one failure will fail.
Configuration Example
# Configure authentication policy
allsuccessfulstrategy = Org.apache.shiro.authc.pam.AllSuccessfulStrategy
SecurityManager.authenticator.authenticationStrategy = $allSuccessfulStrategy
5. Role and permissions based on strings
Writing configuration Files
[Users]
HQQ = 123,role1,role2
lucy = 111,role1
[roles]
role1 = user:select role2
= user:add,user:update,user: Delete
Testing Roles and Permissions
public class Roletest {@Test public void Testhasrole () throws Exception {Subje
CT subject = Shiroutils.login ("Classpath:shiro/shiro-role.ini", "hqq", "123");
Assertequals (True, Subject.hasrole ("Role1"));
Assertequals (True, Subject.hasrole ("Role2"));
Assertequals (True, Subject.hasallroles (Arrays.aslist ("Role1", "Role2"));
Subject.logout (); @Test public void Testcheckrole () throws Exception {Subject Subject = Shiroutils.login ("Classpath:shir
O/shiro-role.ini "," hqq "," 123 ");
Subject.checkrole ("Role1");
Subject.checkrole ("Role2");
Subject.checkroles (Arrays.aslist ("Role1", "Role2"));
Assertequals (True, Subject.hasrole ("Role2")); }
}
public class Permissiontest {
@Test public
void Testhaspermission () throws Exception {Subject
Subject = Shir Outils.login ("Classpath:shiro/shiro-permission.ini", "hqq", "123");
Assertequals (True, subject.ispermitted ("User:select"));
Subject.ispermitted ("User:select", "User:add", "User:delete", "user:update");
Assertequals (True, Subject.ispermittedall ("User:select", "User:select", "User:add", "User:delete", "user:update"));
Subject.logout ();
}
@Test public
void Testcheckpermission () throws Exception {
Subject Subject = Shiroutils.login ("Classpath: Shiro/shiro-permission.ini "," hqq "," 123 ");
Subject.checkpermission ("User:select");
Subject.checkpermissions ("User:select", "User:add", "User:delete", "user:update");
Subject.logout ();
}
6. Custom permission Parser and role resolver
to customize permission resolution rules
Step 1: Implement the Permission interface
public class MyPermission implements Permission {private String ResourceID;
Private String operator;
Private String Instanceid; Public mypermission () {} public mypermission (String permissionstr) {string[] STRs = permissionstr.spli
T ("\\+");
if (Strs.length > 1) {This.resourceid = strs[1]; } if (This.resourceid = null | |
"". Equals (This.resourceid)) {This.resourceid = "*";
} if (Strs.length > 2) {this.operator = strs[2];
} if (Strs.length > 3) {This.instanceid = strs[3]; } if (This.instanceid = null | |
"". Equals (This.instanceid)) {This.instanceid = "*";
System.out.println (=> when instantiating mypermission + this.tostring ()); /** * "This is a very important method" * by the programmer to write their own authorization to match the logic, * Our implementation here is the Realm given in the Permission and INI configuration specified in the PERMISSIONR Permi specified in the Esoler