Copyright Notice: Author original, reproduced please indicate the source.
This series of articles directory address: http://blog.csdn.net/u011961421/article/details/79416510 Introduction
Shiro is an open source security framework for Apache that is designed to simplify authentication and authorization, primarily for authentication, authorization, enterprise session management and encryption, and Shiro is not dependent on any container for use in Javase and Java EE projects.
Compared to the spring family spring Security,shiro in maintaining a strong function, but also has a simple and flexible light weight and other characteristics, learning costs are much lower, at present by more and more project system application, more about Shiro introduction can own Baidu, here is not tricky. actual Combat
The following is the Springboot integrated Shiro, the implementation of basic login authentication and rights management process.
I. Introduction of dependent Files
<!--Shiro---
<dependency>
<groupId>org.apache.shiro</groupId>
< artifactid>shiro-spring</artifactid>
<version>1.4.0</version>
</dependency>
Note that there is a need to introduce shiro-ehcache to implement the cache at the same time, my side because of the integration of the use of Redis later, so it is not introduced. The introduction of Shiro-ehcache is not complicated, add a configuration can self-Baidu, for distributed deployment, there is no need to use Shiro-ehcache.
two. Basic Tables
This article describes the table structure using simple user + permissions, requires three tables, user tables, role tables, and relational tables, and the SQL table is built as follows
CREATE TABLE Cms_user_info (ID integer () not null auto_increment comment ' user ID ', User_code varchar () Not NULL comment ' user code ', user_name varchar (+) NOT null comment ' user name ', user_pwd varchar (comment) ' User password ', REMARK varchar comment ' remarks ', create_by varchar comme NT ' creator ', create_date datetime comment ' creation time ', modified_by varchar comment ' modified person ', modified_ DATE datetime comment ' modified time ', Sortno integer (2) Default 0 Comment ' sort ', state in
Teger (2) Comment ' data status ', primary key (ID)); CREATE TABLE Cms_role_info (ID Integer (TEN) not null auto_increment comment ' role number ', Role_code varchar () Not NULL comment ' role code ', Role_name varchar NOT null comment ' role name ', create_by varchar (comment) ' Creator ', create_date datetime comment ' creation time ', modified_by varchar (comment) ' modifier ', modified_date datetime comment ' modified time ', Sortno integer (2) de
Fault 0 Comment ' sort ', state integer (2) Comment ' data status ', primary key (ID));
CREATE TABLE Cms_user_role_r (ID int not NULL auto_increment, User_code varchar (10), Role_code varchar (ten), create_by varchar comment ' creator ', Create_date datetime CO Mment ' creation time ', modified_by varchar comment ' modifier ', modified_date datetime comment ' modified time ', SORTN
O integer (2) Default 0 Comment ' sort ', state integer (2) Comment ' data status ', primary key (ID) );
The test data is as follows
INSERT into ' Cms_user_info ' VALUES (1, ' admin ', ' admin ', ' d0970714757783e6cf17b26fb8e2298f ', ' Test Notes ', ' admin ', ' 2017-12-8 20 : 32:02 ', ' admin ', ' 2017-12-8 20:32:09 ', 0, 1);
INSERT into ' Cms_user_info ' VALUES (2, ' 17040406 ', ' Zhang San ', ' d0970714757783e6cf17b26fb8e2298f ', ' Test Notes ', ' admin ', ' 2017-12-8 20:32:02 ', ' admin ', ' 2017-12-8 20:32:09 ', 1, 1);
INSERT into ' Cms_role_info ' VALUES (1, ' admin ', ' system administrator ', ' admin ', ' 2017-12-8 19:06:35 ', ' admin ', ' 2017-12-8 19:06:39 ', 0, 1);
INSERT into ' Cms_role_info ' VALUES (2, ' guest ', ' guest ', ' admin ', ' 2017-12-8 19:06:35 ', ' admin ', ' 2017-12-8 19:06:35 ', 1, 1);
INSERT into ' Cms_user_role_r ' VALUES (1, ' admin ', ' admin ', ' admin ', ' 2017-12-8 20:19:34 ', ' admin ', ' 2017-12-8 20:19:3 4 ', 0, 1);
INSERT into ' Cms_user_role_r ' VALUES (2, ' 17040406 ', ' guest ', ' admin ', ' 2017-12-8 20:19:34 ', ' admin ', ' 2017-12-8 20:19:34 ') , 0, 1);
three. When integrating Shiro in the configuration Shiro
Springboot, because the configuration file is omitted, you need to write the configuration class and inject the configuration class using @configuration annotations. Here the simplest Shiro configuration needs to contain three methods:
1. Registering a realm to spring Bean,realm is a specific implementation of authentication and authorization, a method that Shiro for the user to implement, Its simplicity also lies in the need to implement this interface to use Shiro.
2. Register SecurityManager Security Manager, no special need to use the default manager, SecurityManager is the main portal of Shiro, the configuration method to inject the user-defined realm SecurityManager.
3. Configure the filter access policy, please look at the code here, I believe the detailed annotations can be understood. as follows:
Package Com.pf.org.cms.common;
Import Org.apache.shiro.mgt.SecurityManager;
Import Org.apache.shiro.realm.Realm;
Import Org.apache.shiro.spring.web.ShiroFilterFactoryBean;
Import Org.apache.shiro.web.mgt.DefaultWebSecurityManager;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory;
Import org.springframework.beans.BeansException;
Import Org.springframework.beans.factory.annotation.Qualifier;
Import Org.springframework.context.ApplicationContext;
Import Org.springframework.context.ApplicationContextAware;
Import Org.springframework.context.annotation.Bean;
Import org.springframework.context.annotation.Configuration;
Import Java.util.LinkedHashMap; /** * @Auther: PF * @Date: 2017/12/12 19:34 * @Description: Shiro Configuration Component */@Configuration public class Shiroconfiguratio
n {private static final Logger log = Loggerfactory.getlogger (Shiroconfiguration.class);
/** * Inject Realm * @return Myrealm */@Bean (name = "Myrealm") public Myrealm Myauthrealm () { Myrealm Myrealm = new Myrealm ();
Log.info ("Myrealm registration completed");
return Myrealm; }/** * Injected SecurityManager * @param myrealm * @return SecurityManager */@Bean (name = "Securi Tymanager ") Public SecurityManager SecurityManager (@Qualifier (" Myrealm ") Myrealm Myrealm) {Defaultwebsecuritym
Anager manager = new Defaultwebsecuritymanager ();
Manager.setrealm (Myrealm);
Log.info ("SecurityManager registration completed");
Return manager; }/** * Inject filter * @param securitymanager * @return Shirofilterfactorybean */@Bean (name = "s Hirofilter ") Public Shirofilterfactorybean Shirofilter (@Qualifier (" SecurityManager ") SecurityManager
SecurityManager) {Shirofilterfactorybean Filterfactorybean = new Shirofilterfactorybean ();
Filterfactorybean.setsecuritymanager (SecurityManager);
Configure the login URL and login successful URL filterfactorybean.setloginurl ("/auth/login"); Filterfactorybean.setsuCcessurl ("Home");
Configure unauthorized Jump page Filterfactorybean.setunauthorizedurl ("/errorpage/403");
Configure access rights linkedhashmap<string, string> filterchaindefinitionmap = new linkedhashmap<> (); Filterchaindefinitionmap.put ("/css/**", "anon");
Indicates that filterchaindefinitionmap.put can be accessed anonymously ("/fonts/**", "anon");
Filterchaindefinitionmap.put ("/imgs/**", "anon");
Filterchaindefinitionmap.put ("/js/**", "anon");
Filterchaindefinitionmap.put ("/auth/**", "anon");
Filterchaindefinitionmap.put ("/errorpage/**", "anon");
Filterchaindefinitionmap.put ("/demo/**", "anon");
Filterchaindefinitionmap.put ("/swagger-*/**", "anon");
Filterchaindefinitionmap.put ("/swagger-ui.html/**", "anon");
Filterchaindefinitionmap.put ("/webjars/**", "anon");
Filterchaindefinitionmap.put ("/v2/**", "anon"); Filterchaindefinitionmap.put ("/admin/**", "roles[admin]");//means that the admin permission is accessible, and multiple quotes are separated by commas filteRchaindefinitionmap.put ("/*", "authc");//indicates that authentication is required to access Filterchaindefinitionmap.put ("/**", "authc");
Filterchaindefinitionmap.put ("/*.*", "authc");
Filterfactorybean.setfilterchaindefinitionmap (FILTERCHAINDEFINITIONMAP);
Log.info ("Shirofilter registration completed");
return Filterfactorybean;
}
}
Note Shiro supports configuration paths, page labels, annotations, and more, as well as different granularity of permissions configuration.
1. How to configure:
Default filter (10) anon--org.apache.shiro.web.filter.authc.AnonymousFilter authc--Org.apache.shiro.web.filter.authc.Form Authenticationfilter Authcbasic--org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter perms-- Org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter Port--
Org.apache.shiro.web.filter.authz.PortFilter Rest--Org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter Roles--Org.apache.shiro.web.filter.authz.RolesAuthorizationFilter SSL-- Org.apache.shiro.web.filter.authz.SslFilter User--Org.apache.shiro.web.filter.authc.UserFilter logout--
Org.apache.shiro.web.filter.authc.LogoutFilter Anon: Example/admins/**=anon has no parameters, which means it can be used anonymously. AUTHC: For example,/ADMINS/USER/**=AUTHC indicates the need for authentication (login) to use, no parameters roles: Example/admins/user/**=roles[admin], parameters can be written more than one, you must enclose the quotation marks,
And the parameters are separated by commas, when there are multiple parameters, such as admins/user/**=roles["Admin,guest"], each parameter is passed, equivalent to the Hasallroles () method. Perms: Example/admins/user/**=perms[user:add:*], parameters can be written multiple, multiple must be quoted, and the parameters are separated by commas, for example/admins/user/**=perms["user:add:*,user:modify:*"], when there are multiple parameters must be passed through each argument, want to be in the Ispermitedall () method.
Rest: Example/admins/user/**=rest[user], according to the method requested, equivalent to/admins/user/**=perms[user:method], where method is Post,get,delete, etc. Port: Example/admins/user/**=port[8081], when the port of the requested URL is not 8081 is jump to schemal://servername:8081?querystring, Where Schmal is the protocol HTTP or HTTPS, etc., servername is the host,8081 you access is the port in the URL configuration, querystring is the URL you visit.
The following parameters. Authcbasic: For example/admins/user/**=authcbasic no parameter represents HTTPBASIC authentication SSL: Example/admins/user/**=ssl no parameters, represents a secure URL request, the protocol is HTTPS user:
For example,/admins/user/**=user does not have a parameter indicating that a user must exist and does not check when logging in
2. Annotation method Requiresauthentication: Class, instance, annotated with this annotation, the current subject must be authenticated in the current session when accessing or invoking the method. Requiresguest: Class, instance, annotated with this callout, the current subject can be a "gust" identity when accessed or invoked, and does not require authentication or a record in the previous session. Requirespermissions: The method that is labeled by this annotation can be executed if the current subject needs to have certain permissions. If the current subject does not have such a permission, the method will not be executed. Requiresroles: When the current subject must have all the roles specified, you can access the method that is labeled by the annotation. The method does not execute and throws a Authorizationexception exception if the subject has all the specified roles when the day is different. Requiresuser: The current subject must be an app user to access or invoke the class, instance, or method that is labeled by the callout.
3. Page Label: Bo Master use less, the application scenario is also relatively few, can own Baidu, here do not introduce.
four. Writing Myrealm
As the 3rd said, because Shiro does not know the specific logic of your login authentication and authorization specific logic, so users need to implement their own, inherit Authorizingrealm, Implement Dogetauthorizationinfo (Authorization) and Dogetauthenticationinfo (login authentication) Two abstract methods, the specific code is as follows:
Package Com.pf.org.cms.common;
Import Com.pf.org.cms.entity.UserInfo;
Import Com.pf.org.cms.entity.UserRoleInfo;
Import Com.pf.org.cms.service.UserService;
Import Com.pf.org.cms.utils.MD5Util;
Import org.apache.shiro.authc.*;
Import Org.apache.shiro.authz.AuthorizationInfo;
Import Org.apache.shiro.authz.SimpleAuthorizationInfo;
Import Org.apache.shiro.realm.AuthorizingRealm;
Import org.apache.shiro.subject.PrincipalCollection;
Import Org.apache.shiro.util.ByteSource;
Import org.springframework.beans.factory.annotation.Autowired;
Import Java.util.HashMap;
Import java.util.List;
Import Java.util.Map; /** * @Auther: PF * @Date: 2017/12/12 19:29 * @Description: Authentication and authorization specific implementation */public class Myrealm extends Authorizingrealm
{@Autowired private userservice userservice; /** * for current subject license * @param principalcollection * @return authorizationinfo */@Override Prote CTED authorizationinfo dogetauthorizationinfo (principalcollection principalcollection){map<string, object> params = new hashmap<> ();
Params.put ("Usercode", (String) Super.getavailableprincipal (principalcollection));
list<userroleinfo> Userroleinfos = Userservice.getuserroleinfos (params);
Simpleauthorizationinfo info = new Simpleauthorizationinfo (); if (!userroleinfos.isempty ()) {for (Userroleinfo Role:userroleinfos) {info.addrole (role.getr
Olecode ());
}} return info; }/** * Authentication login Subject * @param authenticationtoken * @return AuthenticationInfo * @throws authent Icationexception */@Override protected AuthenticationInfo dogetauthenticationinfo (Authenticationtoken authen Ticationtoken) throws Authenticationexception {Usernamepasswordtoken token = (Usernamepasswordtoken) Authenticati
Ontoken;
map<string, object> params = new hashmap<> (); Params.put ("Usercode", (String) AuthenticatioNtoken.getprincipal ());
list<userinfo> Userinfos = Userservice.getuserinfos (params);
if (Userinfos.isempty ()) {throw new unknownaccountexception ();
} else if (Userinfos.size () > 1) {throw new disabledaccountexception ();
} else {UserInfo user = Userinfos.get (0); Verify password return new Simpleauthenticationinfo (Authenticationtoken.getprincipal (), User.getuserpwd (), Bytesource.
Util.bytes ("2w@w"), GetName ()); }
}
}
Five. Login and authorization Verification
The following is the login controller:
Package com.pf.org.cms.web;
Import com.pf.org.cms.common.IConstants;
Import Com.pf.org.cms.entity.JsonBean;
Import Com.pf.org.cms.utils.ParamUtils;
Import Org.apache.commons.collections.MapUtils;
Import Org.apache.shiro.SecurityUtils;
Import org.apache.shiro.authc.AuthenticationException;
Import org.apache.shiro.authc.DisabledAccountException;
Import org.apache.shiro.authc.UnknownAccountException;
Import Org.apache.shiro.authc.UsernamePasswordToken;
Import Org.apache.shiro.subject.Subject;
Import Org.slf4j.Logger;
Import Org.slf4j.LoggerFactory;
Import Org.springframework.stereotype.Controller;
Import org.springframework.web.bind.annotation.RequestMapping;
Import Org.springframework.web.bind.annotation.ResponseBody;
Import Javax.servlet.http.HttpServletRequest;
Import Java.util.Map; /** * @Auther: PF * @Date: 2017/12/12 19:41 * @Description: */@Controller @RequestMapping (value = "/auth") public CLA SS Authenticationcontroller {private static final Logger log = Loggerfactory. GetLogger (Authenticationcontroller.class);
@RequestMapping (value = "/login") public String login () {return '/login '; } @ResponseBody @RequestMapping (value = "/login_in", produces = "application/json;charset=utf-8") public JSON
Bean Loginin (HttpServletRequest request) {Jsonbean Rejson = new Jsonbean ();
Map Parammap = paramutils.handleservletparameter (request);
String Usercode = maputils.getstring (Parammap, "Usercode");
String userpwd = maputils.getstring (Parammap, "userpwd");
Shiro Certified Subject Subject = Securityutils.getsubject ();
Usernamepasswordtoken token = new Usernamepasswordtoken (Usercode, userpwd);
try {subject.login (token);
} catch (Unknownaccountexception e) {rejson.setmessage ("account does not exist");
return Rejson;
} catch (Disabledaccountexception e) {rejson.setmessage ("there is a problem with the account");
return Rejson; } catch (AuThenticationexception e) {rejson.setmessage ("Incorrect password");
return Rejson; } catch (Exception e) {log.info ("login Exception", e)