SpringBoot之集成Shiro

环境 SpringBoot2.0

<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;
    }

}

自定义一个MyShiroRealm

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 "用户删除";
    }



}

猜你喜欢

转载自www.cnblogs.com/zengnansheng/p/11117478.html