1. 程式人生 > >Shiro練習小Demo(SpringBoot)

Shiro練習小Demo(SpringBoot)

本Demo是用SpringBoot+Mybatis+Shiro
省略建立SpringBoot的截圖流程
匯入jar包

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

整個專案結構

shiro一般都在service(業務層)內
CredentialMatcher類是自定義登陸驗證規則
AuthRealm類是每次登陸授權時需要使用的類
shiroConfiguration類是shiro的總配置檔案
從大到小的順序是 shiroConfiguration→AuthRealm→CredentialMatcher

CredentialMatcher

package com.hjy.serivce;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;

/**
 * 自定義登陸檢驗規則
 */
public class CredentialMatcher extends SimpleCredentialsMatcher {

    //自定義驗證規則
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken) token;
        //session的密碼
        String password =new String(usernamePasswordToken.getPassword());
        //資料庫對應的密碼
        String dePassword=info.getCredentials().toString();
        //返回對比結果
        return this.equals(password,dePassword);
    }
}

AuthRealm
PS:我的dao和service只寫一個方法就是通過傳使用者名稱來查詢對應使用者角色許可權資訊

package com.hjy.serivce;

import com.hjy.entity.Permission;
import com.hjy.entity.Role;
import com.hjy.entity.Users;
import org.apache.commons.collections.CollectionUtils;
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.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 驗證授權類
 */

public class AuthRealm extends AuthorizingRealm {

    @Autowired(required = false)
    private UsersService usersService;

    //授權(每次驗證許可權或角色都會走這個方法)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //從session裡面獲取當前使用者
        Users users=(Users) principalCollection.fromRealm(this.getClass().getName()).iterator().next();
        //存放給info新增所有關係集合
        List<String> permissionList=new ArrayList<>();
        //所有角色集合
        Set<Role> roleSet=users.getRoles();
        //存放給info新增的角色集合
        List<String> roleNameList=new ArrayList<>();
        //判斷角色是否為空
        if (CollectionUtils.isNotEmpty(roleSet)){
            for (Role role : roleSet){
                //獲取所有角色資訊後新增進集合(存放到info)
                roleNameList.add(role.getRname());
                //獲取所有關係集合
                Set<Permission> permissionSet=role.getPermissions();
                if (org.apache.commons.collections.CollectionUtils.isNotEmpty(permissionSet)){
                    for (Permission permission:permissionSet){
                        //獲取所有許可權後新增進集合
                        permissionList.add(permission.getName());
                    }
                }
            }
        }
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addStringPermissions(permissionList);
        info.addRoles(roleNameList);
        System.out.println("授權");
        return info;
    }

    //認證登陸
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken) authenticationToken;
        String username=usernamePasswordToken.getUsername();
        Users users=usersService.findByUsersName(username);
        System.out.println("登陸");
        return new SimpleAuthenticationInfo(users,users.getPassword(),this.getClass().getName());
    }

    public UsersService getUsersService() {
        return usersService;
    }

    public void setUsersService(UsersService usersService) {
        this.usersService = usersService;
    }
}

shiroConfiguration

package com.hjy.serivce;

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.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;

/**
 * shiro配置整合
 * 最下面是底層,依次向上
 */
@Configuration
public class ShiroConfiguration {

    //把SecurityManager放入Filter過濾內,並配置過濾規則
    @Bean("shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //登出後跳轉的頁面
        shiroFilterFactoryBean.setLoginUrl("/login");
        //登陸成功後跳轉的頁面
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

        //配置過濾規則(過濾規則搜尋DefaultFilter,apache的)
        LinkedHashMap<String,String> filterChainDefinitionMap=new LinkedHashMap<>();
        filterChainDefinitionMap.put("/index","authc");
        filterChainDefinitionMap.put("/login","anon");
        filterChainDefinitionMap.put("/loginUser","anon");
        //下面這個只是允許admin角色使用者訪問
        filterChainDefinitionMap.put("/admin","roles[admin]");
        //只允許擁有該許可權的人才能訪問
        filterChainDefinitionMap.put("/edit","perms[edit]");

        filterChainDefinitionMap.put("/**","user");
        //把規則新增到shiroFilter內
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    //把authRealm放入SecurityManager裡面
    @Bean("securityManager")
    public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm){
        DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
        manager.setRealm(authRealm);
        return manager;
    }

    //把自定義規則通過引數從Spring裡面拿出來用
    @Bean("authRealm")
    public AuthRealm authRealm(@Qualifier("credentialMatcher")CredentialMatcher credentialMatcher){
        AuthRealm authRealm=new AuthRealm();
        //把自定義規則發放如Realm內
        authRealm.setCredentialsMatcher(credentialMatcher);
        return  authRealm;
    }

    //前面的自定義規則(這是一個類)
    @Bean("credentialMatcher")
    public CredentialMatcher credentialMatcher(){
        return new CredentialMatcher();
    }


    //下面兩個是關聯配置
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor=new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
}

Controller層

package com.hjy.controller;

import com.hjy.entity.Users;
import com.hjy.serivce.UsersServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Controller
public class UsersController {

    @Resource
    private UsersServiceImpl usersService;

    public UsersServiceImpl getUsersService() {
        return usersService;
    }

    public void setUsersService(UsersServiceImpl usersService) {
        this.usersService = usersService;
    }

   /* @RequestMapping("/text")
    public String text(){
        return JSONArray.toJSONString(usersService.findByUsersName("admin"));
    }*/

    @RequestMapping("/login")
    public String login(){
        return "login";
    }

    @RequestMapping("/index")
    public String index(){
        return "index";
    }

    @RequestMapping("/logout")
    public String logout(){
        Subject subject=SecurityUtils.getSubject();
        if (subject!=null){
            subject.logout();
        }
        return "redirect:/login";
    }
    @GetMapping
    @ResponseBody
    public String admin(){
        return "只有admin才能看到的";
    }

    //登陸認證
    @RequestMapping("/loginUser")
    public String loginUsers(@RequestParam("username")String username,
                             @RequestParam("password")String password,
                             HttpServletRequest request){
        //傳入使用者名稱和密碼進去
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
        Subject subject=SecurityUtils.getSubject();
        try {
            //開始認證,若出錯則會catch
            subject.login(usernamePasswordToken);
            //獲得物件
            Users users=(Users) subject.getPrincipal();
            //把物件放入session內
            request.getSession().setAttribute("users",users);
            //成功則返回index頁面
            return "redirect:/index";
        } catch (Exception e) {
            //失敗則返回到login頁面
            return "redirect:/login";
        }
    }

    @GetMapping("/edit")
    @ResponseBody
    public String edit(){
        return "edit返回資訊";
    }

    @GetMapping("unauthorized")
    public String unauthorized(){
        return "unauthorized";
    }
}

這是本次Demo的碼雲下載地址https://gitee.com/chijj/shiroDemo1.git