Spring boot integrates Shiro's sample code for single-point logon, springshiro

Source: Internet
Author: User

Spring boot integrates Shiro's sample code for single-point logon, springshiro

What is Shiro?

Shiro is an open-source permission framework of the Java platform for authentication and access authorization. Specifically, the following elements are supported:

  1. Users, roles, permissions (only operation permissions, data permissions must be closely integrated with business needs), resources (URLs ).
  2. The user assigns a role and Defines permissions for the role.
  3. Roles or permissions are supported during access authorization, and multi-level permission definitions are supported.

Q: What is group support?
A: shiro does not support setting permissions for groups by default.

Q: Can I assign roles to a group?
A: Extended Realm allows you to assign roles to A group. In fact, you can assign permissions to all users in the group.

Q: What is data permission support? Defined in the business system?
A: shiro only controls operation permissions. It is used to hide or display control elements on the front end and check resource access permissions. Data permissions are closely related to specific business requirements. shiro itself cannot control data permissions.

Q: What is dynamic permission allocation?
A: extends org. apache. shiro. realm. Realm and supports dynamic permission allocation.

Q: Is it integrated with Spring?
A: It can be integrated with Spring. shiro also supports jsp labels.

In the previous blog, we talked about Shiro's two major features: authentication and authorization. Single-point logon is also part of authentication. By default, shiro has already implemented integration with Cas for us, so we can add some integration configurations.

1. Add the shiro-cas package

<! -- Shiro integrates cas single point --> <dependency> <groupId> org. apache. shiro </groupId> <artifactId> shiro-cas </artifactId> <version> 1.2.4 </version> </dependency>

2. Add the Single Sign-On Configuration

Here, I will paste all the configurations for your reference. Detailed descriptions are provided in the configuration.

Package com. chhliu. springboot. shiro. config; import java. util. linkedHashMap; import java. util. map; import javax. servlet. filter; import org. apache. shiro. cache. ehcache. ehCacheManager; import org. apache. shiro. cas. casFilter; import org. apache. shiro. cas. casSubjectFactory; import org. apache. shiro. spring. lifecycleBeanPostProcessor; import org. apache. shiro. spring. security. interceptor. authorizationAttributeS OurceAdvisor; import org. apache. shiro. spring. web. shiroFilterFactoryBean; import org. apache. shiro. web. mgt. defaultWebSecurityManager; import org. jasig. cas. client. session. singleSignOutFilter; import org. jasig. cas. client. session. singleSignOutHttpSessionListener; import org. springframework. aop. framework. autoproxy. defaultAdvisorAutoProxyCreator; import org. springframework. boot. web. servlet. filterRegistra TionBean; import org. springframework. boot. web. servlet. servletListenerRegistrationBean; import org. springframework. context. annotation. bean; import org. springframework. context. annotation. configuration; import org. springframework. context. annotation. dependsOn; import org. springframework. core. ordered; import org. springframework. core. annotation. order; import org. springframework. web. filter. delegatingFilt ErProxy;/*** Shiro configuration ** the Apache Shiro core is implemented through Filter, just like SpringMvc master control through DispachServlet. Since * Filter is used, it can be guessed that the URL rule is used for filtering and permission verification. Therefore, we need to define a series of URL rules and access permissions. ** @ Author chhliu */@ Configuration public class ShiroConfiguration {// cas server address public static final String casServerUrlPrefix = "http: // 127.0.0.1 "; // Cas logon page address: public static final String casLoginUrl = casServerUrlPrefix + "/login"; // Cas logout page address: public static final String casLogoutUrl = casServerUrlPrefix + "/logout "; // public static final String shiroServerUrlPrefix = "http: // 127.0.1.28: 8080 "; // casFilter UrlPattern public static final String casFilterUrlPattern ="/index "; // The logon address is public static final String loginUrl = casLoginUrl + "? Service = "+ shiroServerUrlPrefix + casFilterUrlPattern; // logout address (casserver enables service jump function, must be in webapps \ cas \ WEB-INF \ cas. in the properties file, enable cas. logout. followServiceRedirects = true) public static final String logoutUrl = casLogoutUrl + "? Service = "+ loginUrl; // logon success address // public static final String loginSuccessUrl ="/index "; // permission authentication failure jump address public static final String unauthorizedUrl = "/error/403.html";/*** instantiate SecurityManager, this class is the shiro core class * @ return */@ Bean public DefaultWebSecurityManager securityManager () {defawebwebsecuritymanager securityManager = new DefaultWebSecurityManager (); securityManager. setRealm (myShiroCasRealm ());// <! -- User authorization/authentication information Cache, using EhCache Cache --> securityManager. setCacheManager (getEhCacheManager (); // specify the SubjectFactory. To implement the remember me function of cas, use the following CasSubjectFactory and set it to securityManager's subjectFactory. setSubjectFactory (new CasSubjectFactory (); return securityManager;}/*** configure cache * @ return */@ Bean public EhCacheManager failed () {EhCacheManager em = new EhCacheManager (); em. SetCacheManagerConfigFile ("classpath: config/ehcache-shiro.xml"); return em;}/*** configure Realm, since we use CasRealm, so we have integrated the Single Sign-On function * @ param cacheManager * @ return */@ Bean public MyShiroRealm myShiroCasRealm () {MyShiroRealm realm = new MyShiroRealm (); // cas Login server address prefix realm. setCasServerUrlPrefix (ShiroConfiguration. casServerUrlPrefix); // client callback address, the redirection address after Successful Logon (your own service address) realm. setCasService (ShiroConfiguration. ShiroServerUrlPrefix + ShiroConfiguration. casFilterUrlPattern); // default role after successful logon. The default role is user realm. setDefaultRoles ("user"); return realm;}/*** register the listener for single-point logout * @ return */@ SuppressWarnings ({"rawtypes", "unchecked "}) @ Bean @ Order (Ordered. HIGHEST_PRECEDENCE) // The Filter public ServletListenerRegistrationBean with a higher priority than that of Cas <?> SingleSignOutHttpSessionListener () {ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean (); bean. setListener (new SingleSignOutHttpSessionListener (); bean. setEnabled (true); return bean;}/*** register single-point logout filter * @ return */@ Bean public FilterRegistrationBean singleSignOutFilter () {FilterRegistrationBean bean = new FilterRegistrationBean (); bean. setName ("singleSignOutFilter"); bean. setFilter (new SingleSignOutFilter (); bean. addUrlPatterns ("/*"); bean. setEnabled (true); return bean;}/*** register logging (Shiro) */@ Bean public FilterRegistrationBean DelegatingFilterProxy () {FilterRegistrationBean filterRegistration = new FilterRegistrationBean (); filterRegistration. setFilter (new DelegatingFilterProxy ("shiroFilter"); // The default value is false, indicating that the lifecycle is managed by SpringApplicationContext. If it is set to true, it indicates that filterRegistration is managed by ServletContainer. addInitParameter ("targetFilterLifecycle", "true"); filterRegistration. setEnabled (true); filterRegistration. addUrlPatterns ("/*"); return filterRegistration;}/*** this class can guarantee org. apache. shiro. util. the init or destory method of the shiro object of the Initializable interface is automatically called, * instead of manually specifying the init-method or destory-method * Note: If this class is used, you do not need to manually specify the initialization and destruction methods. Otherwise, an error occurs * @ return */@ Bean (name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor () {return new LifecycleBeanPostProcessor ();}/*** the following two configurations are mainly used to enable shiro aop annotation support. use proxy mode. Therefore, you must enable code support. * @ return */@ Bean @ DependsOn ("lifecycleBeanPostProcessor") public authentication handler () {DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator. setProxyTargetClass (true); return daap;}/*** @ param securityManager * @ return */@ Bean public securityManager (defawebwebsecuritymanager securityManager) {AuthorizationAttributeSourceAdvisor = new principal (); authorizationAttributeSourceAdvisor. setSecurityManager (securityManager); return authorizationAttributeSourceAdvisor;}/*** CAS filter * @ return */@ Bean (name = "casFilter") public CasFilter getCasFilter () {CasFilter casFilter = new CasFilter (); casFilter. setName ("casFilter"); casFilter. setEnabled (true); // the URL to jump to after logon failure, that is, Shiro executes the doGetAuthenticationInfo method of CasRealm to verify tiket casFilter to CasServer. setFailureUrl (loginUrl); // The logon page is casFilter. setLoginUrl (loginUrl); return casFilter;}/*** use factory mode, create and initialize ShiroFilter * @ param securityManager * @ param casFilter * @ return */@ Bean (name = "shiroFilter") public ShiroFilterFactoryBean getShiroFilterFactoryBean (defawebsecuritymanager securityManager, CasFilter casFilter) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean (); // SecurityManager shiroFilterFactoryBean must be set. setSecurityManager (securityManager); // if this parameter is not set, the system automatically searches for "/login. jsp "Page shiroFilterFactoryBean. setLoginUrl (loginUrl);/** the connection to be redirected after successful logon. If this parameter is not set, it will jump to the url of the previous step by default. * For example, enter http in the browser: // localhost: 8080/userlist: 8080/userlist page instead of the index page after successful logon * this field is not recommended * // shiroFilterFactoryBean. setSuccessUrl (loginSuccessUrl); // set the shiroFilterFactoryBean on the page without permission. setUnauthorizedUrl (unauthorizedUrl);/** add casFilter to shiroFilter. Note that the casFilter must be placed before shiroFilter, * This ensures that the program enters single-point authentication before logging on to shiro login */Map <String, Filter> filters = new LinkedHashMap <> (); filters. put ("casFilter", casFilter); // logout has been replaced by the logout for single-point logon // filters. put ("logout", logoutFilter (); shiroFilterFactoryBean. setFilters (filters); loadShiroFilterChain (shiroFilterFactoryBean); return shiroFilterFactoryBean;}/*** load shiroFilter permission control rules (read from the database and then configure ), the role/permission information is obtained by using the doGetAuthorizationInfo provided by the MyShiroCasRealm object. * production stores this rule in the database * @ param shiroFilterFactoryBean */private void loadShiroFilterChain (ShiroFilterFactoryBean response) {// The following rule configurations are best configured in the configuration file. Note, the filter added here must be ordered, so the LinkedHashMap // Map <String, string> filterChainDefinitionMap = new LinkedHashMap <String, String> (); filterChainDefinitionMap. put (casFilterUrlPattern, "casFilter"); // 2. the request filterChainDefinitionMap is not blocked. put ("/css/**", "anon"); filterChainDefinitionMap. put ("/js/**", "anon"); filterChainDefinitionMap. put ("/login", "anon"); // set the logout page to anon instead of logout, because logout is processed by a single vertex, instead of being intercepted by shiro's logoutFilter, filterChainDefinitionMap. put ("/logout", "anon"); filterChainDefinitionMap. put ("/error", "anon"); // 3. intercepted requests (obtained from the local database or obtained from the casserver (webservice, http, and other remote methods), to see where your role permission is configured) filterChainDefinitionMap. put ("/user", "authc"); // login required // 4. logons do not intercept filterChainDefinitionMap. put ("/**", "authc"); shiroFilterFactoryBean. setFilterChainDefinitionMap (filterChainDefinitionMap );}}

Partial configuration reference: http://shiro.apache.org/spring.html

3. Compile Realm

To integrate the Single Sign-On function, we need to integrate the CasRealm class. This class has implemented the single point authentication function for us. What we need to do is implement the authorization function. The sample code is as follows:

Package com. chhliu. springboot. shiro. config; import javax. annotation. resource; import org. apache. shiro. securityUtils; import org. apache. shiro. authc. authenticationInfo; import org. apache. shiro. authc. authenticationToken; import org. apache. shiro. authz. authorizationInfo; import org. apache. shiro. authz. simpleAuthorizationInfo; import org. apache. shiro. cas. casRealm; import org. apache. shiro. subject. principal Collection; import com. chhliu. springboot. shiro. mode. sysPermission; import com. chhliu. springboot. shiro. mode. sysRole; import com. chhliu. springboot. shiro. mode. userInfo; import com. chhliu. springboot. shiro. service. userInfoService;/*** core permission verification class, therefore, you do not need to perform identity authentication. You only need to authorize ** @ author chhliu */public class MyShiroRealm extends CasRealm {@ Resource private UserInfoService userInfoService;/*** 1, CAS Authentication: authenticate user identity * 2. set basic user information to the session for convenient access * 3. You can directly use the authentication method in CasRealm, this is only used for testing */@ Override protected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken token) {// call the authentication method in the parent class. CasRealm has implemented single point authentication for us. AuthenticationInfo authc = super. doGetAuthenticationInfo (token); // obtain the Logon account. After cas authentication is successful, the account will be saved as String account = (String) authc. getPrincipals (). getPrimaryPrincipal (); // saves the user information to the session for the convenience of the program. Here, you can put the user information queried Based on the Logon account into the session SecurityUtils. getSubject (). getSession (). setAttribute ("no", account); return authc;}/*** this method calls hasRole, which is called only when hasPermission is enabled. ** permission information. (authorization): 1. If the user Exits normally, the cache is automatically cleared; 2. If the user exits abnormally, the cache is automatically cleared. NULL; * 3. If the user's permissions are modified and the user does not exit the system, the modified permissions cannot take effect immediately. (Manual programming is required for implementation; put it in service for calling) * call the method in realm after permission modification. realm is managed by spring, so get the realm instance from spring and call the receivached method; *: Authorization is an authorized access control. It is used to authorize a user's operations and verify whether the user is allowed to perform the current operations, such as accessing a link or a resource file. ** @ Param principals * @ return */@ Override protected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principals) {System. out. println ("permission configuration --> MyShiroRealm. doGetAuthorizationInfo () "); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo (); // you can obtain the username after single-point logon from the session, because after successful authentication, the user name has been put into the session String userName = (String) super. getAvailablePrincipal (principals); // principals. getPrimaryPrincipal (); you can also obtain the user name // obtain the role and permission information of the user based on the user name UserInfo userInfo = userInfoService. findByUsername (userName); // package the role and permission information of the user into AuthorizationInfo for (SysRole role: userInfo. getRoleList () {authorizationInfo. addRole (role. getRole (); for (SysPermission p: role. getPermissions () {authorizationInfo. addStringPermission (p. getPermission () ;}} return authorizationInfo ;}}

Next, we can perform the verification test!

Enter http: 127.0.1.28: 8080/userInfo/userList in the browser and we will find that the single-point logon page is automatically displayed.

Then, we enter the user name and password to automatically jump to the http: 127.0.1.28: 8080/userInfo/userList page.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Related Article

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.