springboot系列(二):Apache Shiro安全框架的简单使用

    上一篇文章中实践了原始方式实现的登录验证的过程,了解了关于登录验证的一些简单原理。然而在实际项目的开发中,这种方式并不能满足实际安全的需求,而是借助一些框架来实现。目前,Apache Shiro和spring Security是两大最为流行的安全验证框架,相比于Spring Security的功能强大但使用复杂,Apache Shiro更为简单易用,也渐渐更多人使用。


    下面会用从如何入手使用一个框架来说Apache Shiro的简单使用。一般,接触一个框架,可以从以下几个方面说起:基本功能、基本原理、基本使用配置、功能使用扩展。

首先来看基本功能,Shiro最基本的功能有以下四个:

    认证Authentication : 身份认证/登录,即验证用户是否拥有相应的身份。

    授权Authorization : 某个通过认证的用户是否拥有某个权限。

    会话管理Session Manager:一次登录就是一次会话,没有退出之前,所有信息都在会话中。

    cryptography加密 : 如密码加密存储到数据库中。


Shiro实现安全验证的基本原理:

Subject:主体,可以使与当前用户交互的的任务东西

    SecurityManager:Shiro的核心,所有与安全有关的操作都会与SecurityManager交互,相当于SpringMVC的DispatcherServlet前端控制器

    Realm: 域,Shiro从Realm获取安全数据(用户/密码、角色、权限),相当于用于验证的数据源。


根据上图,应用实现安全认证的流程为:

1、应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager;

2、 我们需要给Shiro的SecurityManager注入Realm,从而让SecurityManager能得到合法的用户及权限来进行判断;


在springboot 中使用Shiro的基本过程如下:

1、添加依赖:

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


2、配置,这里的java配置相当于spring MVC中的xml配置

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/admin/403");

        //拦截器.
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        //配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/logout", "logout");

        //<!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->
        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->


        filterChainDefinitionMap.put("/**", "authc");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

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

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


3、Shiro不会去维护用户、维护权限;这些需要我们自己去设计提供;然后通过相应的接口注入Shiro即可,我们可以自定义一个Realm类,继承AuthorizingRealm抽象类,重载doGetAuthenticationInfo(),重写获取用户信息的方法即可,下面让我们来看具体的代码实现:

public class MyShiroRealm extends AuthorizingRealm {

    @Autowired
    private LoginService loginService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        String username = userToken.getUsername();


        List<User> userList = loginService.getUserByNameAndPassword(username, String.valueOf(userToken.getPassword()));
        User user = null;
        if (userList.size() != 0){
            user = userList.get(0);
        }
        if (null == user) {
            return null;
        }


        return new SimpleAuthenticationInfo(user,user.getPassword(),this.getClass().getName());
    }
}


4、好了,上面基本上就是完成了Shiro的基本配置过程,下面是测试的业务代码

页面html:

<head>
    <meta charset="UTF-8" />
    <title>springboot登录</title>
    <style type="text/css">
        ul li{
            list-style: none;
        }
    </style>
</head>
<body>
<div >
    <form name="form" accept-charset="utf-8"  action="/login" method="post">
        <ul >
            <li>
                <label for="username"  class="input-tips2">用户名:</label>
                <div class="inputOuter2">
                    <input type="text" id="username" name="username" maxlength="16" />
                </div>
            </li>
            <li>
                <label for="password" class="input-tips2">密码:</label>
                <div >
                    <input type="password" id="password"  name="password" maxlength="16"/>
                </div>
            </li>
            <li>
                <div >
                    <input type="submit" value="登录"/>
                </div>
            </li>
        </ul>
    </form>
</div>
</body>  

controller:

@Controller
public class LoginController {

    @Autowired
    private LoginService loginService;

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

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

    @PostMapping("/login")
    public String loginVerify(String username,String password){
        try {
            ShiroToken token = new ShiroToken(username,password);
            SecurityUtils.getSubject().login(token);
            return "index";
        } catch (Exception e){
            return "login";
        }
    }
}


小结:

    可以发现Apache Shiro 核心是通过 Filter 来实现的,需要通过URL规则来进行过滤和权限校验,所以我们在上面需要定义一系列关于URL的规则和访问权限。另外,Shiro采用的是RBAC策略, 即是基于角色的访问控制(Role-Based Access Control ),即是权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。由于上面没有实现权限的控制,所以这里没有体现,还有会话管理、加密等功能会在后面实践,敬请期待...

阅读更多
文章标签: springboot Shiro
个人分类: springboot
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭