SpringBoot之集成Shiro

環境 SpringBoot2.0java

<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
ShiroConfig
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        System.out.println("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //攔截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        // 配置不會被攔截的url 順序判斷
        //配置退出 過濾器,其中的具體的退出代碼Shiro已經替咱們實現了
        filterChainDefinitionMap.put("/dologin", "anon");
        filterChainDefinitionMap.put("/logout", "anon");
        //<!-- 過濾鏈定義,從上向下順序執行,通常將/**放在最爲下邊 -->:這是一個坑呢,一不當心代碼就很差使了;
        //<!-- authc:全部url都必須認證經過才能夠訪問; anon:全部url都均可以匿名訪問-->
        filterChainDefinitionMap.put("/**", "authc");
        // 若是不設置默認會自動尋找Web工程根目錄下的"/login.jsp"頁面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登陸成功後要跳轉的連接
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //未受權界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 憑證匹配器
     * (因爲咱們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了
     * )
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:這裏使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(1);//散列的次數,好比散列兩次,至關於 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;
    }

}

自定義一個MyShiroRealmweb

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class MyShiroRealm extends AuthorizingRealm {
    /*認證 主要是用來進行身份認證的,也就是說驗證用戶輸入的帳號和密碼是否正確。*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //把AuthenticationToken轉換成UsernamePasswordToken
        UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken)authenticationToken;
        //獲取username
        String username=usernamePasswordToken.getUsername();
        //根據username從數據庫查詢信息(注入並調用UserService方法),此處省略

        //根據獲取的用戶信息,決定是否拋出AuthenticationException異常,此處寫死
        if(username.equals("unknown")){
            throw new UnknownAccountException("用戶不存在!");
        }
        if (username.equals("lock")) {
            throw new LockedAccountException("用戶被鎖定!");
        }

        //構建並返回AuthenticationInfo,一般是SimpleAuthenticationInfo
        //principal:能夠是username,也能夠是用戶實體對象
        //credentials:從數據庫獲取的密碼
        //realmName:當前realm對象的name
        Object principal=username;
        //Object credentials="123456";
        Object credentials=new SimpleHash("MD5", "123456", "", 1);
        String realmName=this.getName();
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(principal, credentials, realmName);
        return info;
    }

    /**
     * 受權 權限信息,包括角色以及權限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("權限配置-->MyShiroRealm.doGetAuthorizationInfo()");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //若是身份認證的時候沒有傳入User對象,這裏只能取到userName
        //也就是SimpleAuthenticationInfo構造的時候第一個參數傳遞須要User對象
        String userName  = (String)principalCollection.getPrimaryPrincipal();

        //根據username從數據庫查詢角色和權限信息,此處省略

        //構造角色數據
        if(userName.equals("zhangsan")){
            authorizationInfo.addRole("role1");
            authorizationInfo.addRole("role2");
        }
        if(userName.equals("lisi")){
            authorizationInfo.addRole("role1");
        }

        //構造權限數據
        if(userName.equals("zhangsan")){
            authorizationInfo.addStringPermission("user:list");
            authorizationInfo.addStringPermission("user:add");
            authorizationInfo.addStringPermission("user:delete");
        }
        if(userName.equals("lisi")){
            authorizationInfo.addStringPermission("user:list");
        }

        return authorizationInfo;
    }

    public static void main(String[] args) {
        String algorithmName="MD5";
        String source="123456";
        String salt="";
        int hashIterations=1;
        Object result=new SimpleHash(algorithmName, source, salt, hashIterations);
        System.out.println(result);
    }
}
ShiroTestController 模擬登錄後訪問url測試
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("")
public class ShiroTestController {
    @RequestMapping(value = "/dologin")
    public String login() {
        System.out.println("------登陸-------");
        String msg = "";
        //String username = "zhangsan";
        String username = "lisi";
        String password = "123456";
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            if (subject.isAuthenticated()) {
                return "登陸成功";
            } else {
                return "登陸失敗";
            }
        } catch (IncorrectCredentialsException e) {
            msg = "登陸密碼錯誤. Password for account " + token.getPrincipal() + " was incorrect.";
            System.out.println(msg);
        } catch (ExcessiveAttemptsException e) {
            msg = "登陸失敗次數過多";
            System.out.println(msg);
        } catch (LockedAccountException e) {
            msg = "賬號已被鎖定. The account for username " + token.getPrincipal() + " was locked.";
            System.out.println(msg);
        } catch (DisabledAccountException e) {
            msg = "賬號已被禁用. The account for username " + token.getPrincipal() + " was disabled.";
            System.out.println(msg);
        } catch (ExpiredCredentialsException e) {
            msg = "賬號已過時. the account for username " + token.getPrincipal() + "  was expired.";
            System.out.println(msg);
        } catch (UnknownAccountException e) {
            msg = "賬號不存在. There is no user with username of " + token.getPrincipal();
            System.out.println(msg);
        } catch (UnauthorizedException e) {
            msg = "您沒有獲得相應的受權!" + e.getMessage();
            System.out.println(msg);
        }
        return "登陸";
    }

    @RequestMapping(value = "logout", method = RequestMethod.GET)
    public String logout() {
        System.out.println("------退出-------");
        Subject subject = SecurityUtils.getSubject();
        if (subject != null) {
            try{
                subject.logout();
            }catch(Exception ex){
            }
        }
        return "退出成功";
    }

    @RequestMapping("/index")
    public String index(){
        System.out.println("------進入首頁-------");
        return "進入首頁";
    }

    @RequestMapping("/unauthorized")
    public String unauthorized(){
        System.out.println("------未受權-------");
        return "未受權";
    }

    @RequestMapping("/userList")
    @RequiresPermissions("user:list")
    public String userList(){
        System.out.println("------用戶列表-------");
        return "用戶列表";
    }

    @RequestMapping("/userAdd")
    @RequiresPermissions("user:add")
    public String userAdd(){
        System.out.println("------用戶添加-------");
        return "用戶添加";
    }

    @RequestMapping("/userDelete")
    @RequiresPermissions("user:delete")
    public String userDelete(){
        System.out.println("------用戶刪除-------");
        return "用戶刪除";
    }



}
相關文章
相關標籤/搜索