springboot集成shiro

springboot集成shiro

未命名文件 (3)

Shiro和Security其实还是蛮类似的,至少大致的流程是差不多的,区别在于

  • shiro通过token来传递前端的数据,而Security通过绑定特定的页面和属性来实现前端数据的传输。
  • shiro和Security对数据处理功能的封装方式不一样。

而如果我们需要使用Security,只需要自定义一个AuthorizingRealm,并且将自定义的Realm注入容器,并且设置为DefaultWebSecurityManagerInfo的属性,并将DefaultWebSecurityManagerInfo注入到容器,并且设置为ShiroFilterFactoryBean的属性即可。将ShiroFilterFactoryBean注入到IOC容器。

下面用一个Demo来讲解一下大致流程

  1. 前端发送请求

    <a th:href="@{/user/add}">add</a>
    
  2. 拦截请求并处理,需要拦截请求,配置我们的Shiro

    package com.lyj.config;
    
    import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    @Configuration
    public class ShiroConfig {
    
        //整合shiroDialect:用来整和shiro thymeleaf
        @Bean
        public ShiroDialect getShiroDialect(){
            return new ShiroDialect();
        }
    
        //1.Realm 授权器注入容器
        @Bean
        public MyRealm myRealm(){
            return new MyRealm();
        }
    
        //2.DefaultWebSecurityManager权限管理器注入容器,在权限管理器加入我们自己的授权器
        @Bean
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联realm
            securityManager.setRealm(myRealm);
            return securityManager;
        }
    
    
        //3.ShiroFilterFactoryBean 权限规则设置工厂注入容器,在
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //添加shiro的内置过滤器
            /**
             * anon:无需认证即可访问
             * authc:必须认证才可以访问
             * user:必须拥有 记住我 才能用
             * perms:拥有对某个资源的权限才能访问
             * role: 必须拥有某个权限才能访问
             * */
    
            Map<String, String> filterMap = new LinkedHashMap<>();
            filterMap.put("/user/add","perms[user:add]");
            filterMap.put("/user/update","perms[user:update]");
            filterMap.put("/user/*","authc");
            //filterMap.put("/user/*","authc");
    
            //放入过滤链中
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
    
            //设置登录的请求
            shiroFilterFactoryBean.setLoginUrl("/toLogin");
    
            //设置权限验证失败界面
            shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
    
            return shiroFilterFactoryBean;
        }
    
    }
    
    
    package com.lyj.config;
    
    
    import com.lyj.pojo.User;
    import com.lyj.service.UserService;
    import org.apache.shiro.SecurityUtils;
    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.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    
    //自定义realm
    public class MyRealm extends AuthorizingRealm {
    
        @Autowired
        private UserService userService;
    
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("授权中");
    
            //授权器
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            //info.addStringPermission("user:add"); //全部统一加上权限。
    
            //it acquires the Subject based on user data associated with current thread or incoming request.
            //获取当前线程的用户
            Subject subject = SecurityUtils.getSubject();
    
            //Returns this Subject's principals (identifying attributes) in the form of a {@code PrincipalCollection}
            //获取当前subject的身份属性(之前封装成了token)
            User user = (User) subject.getPrincipal();
    
            //设置用户当前权限
            info.addStringPermission(user.getPerms());
            return info;
        }
    
        //从数据库中拿到用户名与密码,并验证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("验证密码中");
    
            //2.得到前端存入的token
            UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
    
            User user = userService.queryUserByName(token.getUsername());
            if (user==null){
                return null;    //
            }
    
            SecurityUtils.getSubject()
                    .getSession()
                    .setAttribute("loginUser",user.getName());
            //密码认证,shiro做
            System.out.println("密码验证中");
            return new SimpleAuthenticationInfo(user,user.getPwd(),"");
        }
    }
    
    
  3. 将前端的请求进行过滤

    Map<String, String> filterMap = new LinkedHashMap<>();
    filterMap.put("/user/add","perms[user:add]");
    filterMap.put("/user/update","perms[user:update]");
    filterMap.put("/user/*","authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
    
  4. 若不在过滤规则,放行

    若已登陆,无权限访问,跳转到指定页面

    shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
    

    若未登录,跳转到登录页面的请求

    shiroFilterFactoryBean.setLoginUrl("/toLogin");
    
  5. 定义跳转到登录页面的请求

    @RequestMapping("/toLogin")
    public String toLogin(){
        return "login";
    }
    
  6. 登录页面发送登录请求

    <form th:action="@{/login}">
        <input name="username" type="text">
        <input name="password" type="password">
        <input type="submit" value="提交">
    </form>
    
  7. 定义登录请求(传入参数,封装到token中,调用shiro处理)

    @RequestMapping("/login")
    public String login(String username, String password, Model model){
        System.out.println("我刚通过login接口进入");
        //获取当前用户
        Subject subject = SecurityUtils.getSubject();    //it acquires the Subject based on user data associated with current thread or incoming request.
        //封装用户数据
        System.out.println("封装前端的数据");
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        System.out.println("封装完毕");
        //执行登录方法
        try{
            //将封装的信息放入subject并且调用shiro的拦截验证
            subject.login(token);
            return "index";
        }catch (UnknownAccountException e){ //用户名不存在
            model.addAttribute("msg","用户名不存在");
            return "login";
        }catch (IncorrectCredentialsException e){
            model.addAttribute("msg","密码错误");
            return "login";
        }
    
    }
    
  8. 验证用户名是否正确

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("验证密码中");
    
        //2.得到前端存入的token
        UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
    
        User user = userService.queryUserByName(token.getUsername());
        if (user==null){
            return null;    //
        }
    
        SecurityUtils.getSubject()
                .getSession()
                .setAttribute("loginUser",user.getName());
        //密码和用户名认证,shiro做
        System.out.println("密码验证中");
        return new SimpleAuthenticationInfo(user,user.getPwd(),"");
    }
    
  9. 给用户授予权限

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授权中");
    
        //授权器
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //info.addStringPermission("user:add"); //全部统一加上权限。
    
        //it acquires the Subject based on user data associated with current thread or incoming request.
        //获取当前线程的用户
        Subject subject = SecurityUtils.getSubject();
    
        //Returns this Subject's principals (identifying attributes) in the form of a {@code PrincipalCollection}
        //获取当前subject的身份属性(之前封装成了token)
        User user = (User) subject.getPrincipal();
    
        //设置用户当前权限
        info.addStringPermission(user.getPerms());
        return info;
    }
    
  10. 再次经过过滤链过滤请求

    Map<String, String> filterMap = new LinkedHashMap<>();
    filterMap.put("/user/add","perms[user:add]");
    filterMap.put("/user/update","perms[user:update]");
    filterMap.put("/user/*","authc");
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
    
  11. 请求通过

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值