1. 程式人生 > >springboot整合shiro+mybatis+mysql

springboot整合shiro+mybatis+mysql

一 、介紹shiro框架

Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼學和會話管理。Shiro 主要分為來個部分就是認證和授權兩部分

Subject

Subject即主體,外部應用與subject進行互動,subject記錄了當前操作使用者,將使用者的概念理解為當前操作的主體,可能是一個通過瀏覽器請求的使用者,也可能是一個執行的程式。 Subject在shiro中是一個介面,介面中定義了很多認證授相關的方法,外部程式通過subject進行認證授,而subject是通過SecurityManager安全管理器進行認證授權

 SecurityManager 

SecurityManager即安全管理器,對全部的subject進行安全管理,它是shiro的核心,負責對所有的subject進行安全管理。通過SecurityManager可以完成subject的認證、授權等,實質上SecurityManager是通過Authenticator進行認證,通過Authorizer進行授權,通過SessionManager進行會話管理等。

SecurityManager是一個介面,繼承了Authenticator, Authorizer, SessionManager這三個介面。

 Authenticator

Authenticator即認證器,對使用者身份進行認證,Authenticator是一個介面,shiro提供ModularRealmAuthenticator實現類,通過ModularRealmAuthenticator基本上可以滿足大多數需求,也可以自定義認證器。

Authorizer

Authorizer即授權器,使用者通過認證器認證通過,在訪問功能時需要通過授權器判斷使用者是否有此功能的操作許可權。

 realm

Realm即領域,相當於datasource資料來源,securityManager進行安全認證需要通過Realm獲取使用者許可權資料,比如:如果使用者身份資料在資料庫那麼realm就需要從資料庫獲取使用者身份資訊。

注意:不要把realm理解成只是從資料來源取資料,在realm中還有認證授權校驗的相關的程式碼。

 sessionManager

sessionManager即會話管理,shiro框架定義了一套會話管理,它不依賴web容器的session,所以shiro可以使用在非web應用上,也可以將分散式應用的會話集中在一點管理,此特性可使它實現單點登入。X

二、shiro的實現

整體的專案目錄

1.新增jar包

<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>1.4.0</version>
</dependency>

2.配置配置檔案

spring.datasource.url= jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#spring.datasource.schema=database/import.sql
spring.thymeleaf.cache=false
spring.thymeleaf.mode=LEGACYHTML5
spring.jpa.database=mysql
#spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.DefaultComponentSafeNamingStrategy
spring.jpa.properties.hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
mybatis.mapper-locations=classpath:mapping/*.xml

3.自定義Realm 繼承AuthorizingRealm 重寫  AuthorizationInfo(授權) 和  AuthenticationInfo(認證)這兩個

public class MyShiroRealm extends AuthorizingRealm {
    @Resource
    private UserInfoService userInfoService;
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("許可權配置-->MyShiroRealm.doGetAuthorizationInfo()");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        SysUser userInfo  = (SysUser)principals.getPrimaryPrincipal();
        Integer uid = userInfo.getUid();

        List<SysRole> r = userInfoService.getAllRole(uid);
        userInfo.setRoleList(r);
        for(SysRole role:userInfo.getRoleList()){
            authorizationInfo.addRole(role.getRole());
            List<SysPermission> per = userInfoService.getAllPermission(role.getId());
            role.setPermissions(per);
            for(SysPermission p:role.getPermissions()){
                authorizationInfo.addStringPermission(p.getPermission());
            }
        }

        return authorizationInfo;
    }

    /*主要是用來進行身份認證的,也就是說驗證使用者輸入的賬號和密碼是否正確。*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        System.out.println("MyShiroRealm.doGetAuthenticationInfo()");
        //獲取使用者的輸入的賬號.
        String username = (String)token.getPrincipal();
        System.out.println(token.getCredentials());
        //通過username從資料庫中查詢 User物件,如果找到,沒找到.
        //實際專案中,這裡可以根據實際情況做快取,如果不做,Shiro自己也是有時間間隔機制,2分鐘內不會重複執行該方法
        SysUser userInfo = userInfoService.findByUsername(username);

        System.out.println("----->>userInfo="+userInfo.getPassword());
        if(userInfo == null){
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                userInfo, //使用者名稱
                userInfo.getPassword(), //密碼
                ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }

}

4.配置過濾配置

@Configuration
public class ShiroConfig {
   @Bean
   public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
      System.out.println("ShiroConfiguration.shirFilter()");
      ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
      shiroFilterFactoryBean.setSecurityManager(securityManager);
      //攔截器.
      //必須是LinkedHashMap,因為要保證有序
      Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
      // 配置不會被攔截的連結 順序判斷
      filterChainDefinitionMap.put("/static/**", "anon");
      filterChainDefinitionMap.put("/submitLogin","anon");
      //配置退出 過濾器,其中的具體的退出程式碼Shiro已經替我們實現了
      filterChainDefinitionMap.put("/logout", "logout");
      //<!-- 過濾鏈定義,從上向下順序執行,一般將/**放在最為下邊 -->:這是一個坑呢,一不小心程式碼就不好使了;
      //<!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問-->
      filterChainDefinitionMap.put("/**", "authc");

      // 如果不設定預設會自動尋找Web工程根目錄下的"/login.jsp"頁面
      shiroFilterFactoryBean.setLoginUrl("/login");
      // 登入成功後要跳轉的連結
      shiroFilterFactoryBean.setSuccessUrl("/index");

      //未授權介面;
      shiroFilterFactoryBean.setUnauthorizedUrl("/403");
      shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
      return shiroFilterFactoryBean;
   }

   /**
    * 憑證匹配器
    * (由於我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了
    * )
    * @return
    */
   @Bean
   public HashedCredentialsMatcher hashedCredentialsMatcher(){
      HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
      hashedCredentialsMatcher.setHashAlgorithmName("md5");//雜湊演算法:這裡使用MD5演算法;
      hashedCredentialsMatcher.setHashIterations(2);//雜湊的次數,比如雜湊兩次,相當於 md5(md5(""));
      return hashedCredentialsMatcher;
   }

   @Bean
   public MyShiroRealm myShiroRealm(){
      MyShiroRealm myShiroRealm = new MyShiroRealm();
      myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
      return myShiroRealm;
   }


   @Bean
   public SecurityManager securityManager(){
      DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
      securityManager.setRealm(myShiroRealm());
      return securityManager;
   }

   /**
    *  開啟shiro aop註解支援.
    *  使用代理方式;所以需要開啟程式碼支援;
    * @param securityManager
    * @return
    */
   @Bean
   public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
      AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
      authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
      return authorizationAttributeSourceAdvisor;
   }

   @Bean(name="simpleMappingExceptionResolver")
   public SimpleMappingExceptionResolver
   createSimpleMappingExceptionResolver() {
      SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
      Properties mappings = new Properties();
      mappings.setProperty("DatabaseException", "databaseError");//資料庫異常處理
      mappings.setProperty("UnauthorizedException","403");
      r.setExceptionMappings(mappings);  // None by default
      r.setDefaultErrorView("error");    // No default
      r.setExceptionAttribute("ex");     // Default is "exception"
      //r.setWarnLogCategory("example.MvcLogger");     // No default
      return r;
   }
}

5.實體類

user 使用者類

@Entity
public class SysUser implements Serializable {
    @Id
    @GeneratedValue
    private Integer uid;
    @Column(unique =true)
    private String username;//帳號
    private String name;//名稱(暱稱或者真實姓名,不同系統不同定義)
    private String password; //密碼;
    private String salt;//加密密碼的鹽
    private byte state;//使用者狀態,0:建立未認證(比如沒有啟用,沒有輸入驗證碼等等)--等待驗證的使用者 , 1:正常狀態,2:使用者被鎖定.
    @ManyToMany(fetch= FetchType.EAGER)//立即從資料庫中進行載入資料;
    @JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "uid") }, inverseJoinColumns ={@JoinColumn(name = "roleId") })
    private List<SysRole> roleList;// 一個使用者具有多個角色

role 角色類

@Entity
public class SysRole {
    @[email protected]
    private Integer id; // 編號
    private String role; // 角色標識程式中判斷使用,如"admin",這個是唯一的:
    private String description; // 角色描述,UI介面顯示使用
    private Boolean available = Boolean.FALSE; // 是否可用,如果不可用將不會新增給使用者

    //角色 -- 許可權關係:多對多關係;
    @ManyToMany(fetch= FetchType.EAGER)
    @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")})
    private List<SysPermission> permissions;

    // 使用者 - 角色關係定義;
    @ManyToMany
    @JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="uid")})
    private List<SysUser> userInfos;// 一個角色對應多個使用者

permission 許可權類

@Entity
public class SysPermission implements Serializable {
    @[email protected]
    private Integer id;//主鍵.
    private String name;//名稱.
    @Column(columnDefinition="enum('menu','button')")
    private String resourceType;//資源型別,[menu|button]
    private String url;//資源路徑.
    private String permission; //許可權字串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:view
    private Long parentId; //父編號
    private String parentIds; //父編號列表
    private Boolean available = Boolean.FALSE;
    @ManyToMany
    @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="permissionId")},inverseJoinColumns={@JoinColumn(name="roleId")})
    private List<SysRole> roles;

6.接下來編寫controller

@RequestMapping(value="/submitLogin",method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> submitLogin(String username,String password){
    System.out.println(username+"-----"+password);
    String msg = "";
    Map<String, Object> map = new HashMap<>();
    try {
        UsernamePasswordToken token = token = new UsernamePasswordToken(username, password);
        char[] password1 = token.getPassword();
        String s = password1.toString();

        System.out.println("*******"+s);
        SecurityUtils.getSubject().login(token);
        token.setRememberMe(true);
        map.put("status",200);
    } catch (UnknownAccountException e) {
        msg = "UnknownAccountException -- > 賬號不存在:";
        map.put("status",400);
    } catch (IncorrectCredentialsException e){
        msg = "IncorrectCredentialsException -- > 密碼不正確:";
        map.put("status",500);
    }catch (Exception exception){
        msg = "else >> "+exception;
        System.out.println("else -- >" + exception);
    }
    return map;
}

相關推薦

springboot整合shiro+mybatis+mysql

一 、介紹shiro框架 Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼學和會話管理。Shiro 主要分為來個部分就是認證和授權兩部分 Subject Subject即主體,外部應用與subject進行互動,subject記錄了當前

dubbo學習(三) springboot整合dubbo mybatis mysql

bubuko nbsp img 查看 boot 消費 mysql mybatis 異常 dubbo-admin查看服務和服務提供方配置 服務消費方配置 和web 整合相對復雜一些,常出現的問題是Controller中 有@Reference配置的屬性 沒註入進來而調

SpringBoot整合Shiro+mybatis-plus

原始碼地址: link 一、新增依賴 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h

Springboot整合Shiro框架(包含mybatis、Durid、Html5、Thymeleaf)

在Springboot中使用Shrio,實現賬號的登入限制、賬號的角色的授權、資源的授權。 以下是我個人從零開始在springboot專案中去整合Shiro框架,僅供參考,但是按照我這個整合是絕對可行的! 我以專案結構的方式去介紹了: 先貼個專案結構目錄圖: 首先

SpringBoot(十四):springboot整合shiro-登錄認證和權限管理

sets man throws 將不 匹配 跳轉 ida 管理員 領域 原文出處: 純潔的微笑 這篇文章我們來學習如何使用Spring Boot集成Apache Shiro。安全應該是互聯網公司的一道生命線,幾乎任何的公司都會涉及到這方面的需求。在Java領域一般有Spri

springboot整合shiro應用

exceptio dst over sql version ges sub star images 1、Shiro是Apache下的一個開源項目,我們稱之為Apache Shiro。它是一個很易用與Java項目的的安全框架,提供了認證、授權、加密、會話管理,與spr

SpringBoot整合Freemarker+Mybatis

strong res esp ngs wire hid names 插件 sql 開發工具 , 開始 新建工程 .選擇Spring Initializr 下一步 下一步,選擇需要的組件 ..改一下工程名,Finish ..目錄結構 首先,修改po

springBoot整合shiro

shiro依賴包 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.

SpringBoot整合Shiro (二)

mark alc depend sco repo 服務 框架 filter des Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼學和會話管理。相比較Spring Security,shiro有小巧、簡單、易上手等的優點。所以很多框架

30分鐘了解Springboot整合Shiro

autowired 常用 ddr 一個 matcher 所有 login tco etime 前言:06年7月的某日,不才創作了一篇題為《30分鐘學會如何使用Shiro》的文章。不在意之間居然斬獲了22萬的閱讀量,許多人因此加了我的聯系方式咨詢源碼工程,只可惜當時並沒有專門

Springboot整合hikaricp mybatis

1.新增Maven依賴 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <

springboot整合shiro遭遇自定義filter異常(自定義FormAuthenticationFilter)

最近忙著研究在 Springboot 上使用 Shiro 的問題。剛好就遇到個詭異事,百度 Google 也沒找到啥有價值的資訊,幾番周折自己解決了,這裡稍微記錄下。 自定義 Filter Shiro 支援自定義 Filter 大家都知道,也經常用,這裡我也用到了一個自定義 Filter,主

SpringBoot整合Shiro許可權管理框架

專案目錄結構 1.pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://

springboot整合shiro+redis

之前整合過ssm+shiro+ehcache,也弄過ssh,這次把springboot+redis整合進去   對應的pom: <!--shiro--> <!-- https://mvnrepository.com/artifact/org.apa

springboot 整合 shiro ehcache

一、我的專案是多模組,這裡shiro單獨一個模組,下面的三個有用到的類   二、新增依賴包 <dependency> <groupId>org.apache.shiro</groupId> <artifactId&

springboot整合shiro無法載入樣式status302

1、攔截配置(按理來說是沒問題的,但是結果就是不講道理。) 2、樣式載入失敗                      3、請求失敗的url不包含static,也許

springboot整合shiro的簡單實現

springboot整合shiro的簡單實現 注意: 1.shiro需要自行在doGetAuthenticationInfo方法中進行賬號密碼的校驗 2.ip+埠形式訪問頁面會被shiro攔截,如果沒有登入會被重定向到login頁面,如果登入會被重定向到index

springboot整合shiro、ehcache

只需要一個自定義realm、一個shiro配置類和ehcache 自定義realm: package com.example.demo.config; import com.example.demo.entity.RoleEntity; import com.example.demo.en

SpringBoot 整合 Shiro框架 簡單配置

SpringBoot整合Shiro框架 pom.xml新增 <!-- shiro框架-->         <dependency>                <

springboot整合shiro swagger時候路徑過濾問題

//swagger介面許可權 開放 filterChainDefinitionMap.put("/swagger-ui.html", "anon"); filterChainDefinitionMap.put("/webjars/**", "anon"); filterChainDefinition