Springboot集成Shiro实现身份认证和权限控制

对比Spring Security

Spring Security,是一个基于Spring的身份验证和访问控制框架。支持主流的认证方式(HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等)。授权方面,提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。

官网:https://spring.io/projects/spring-security 

Apache Shiro,依赖性低,可以独立运行不依赖Spring,当然也可以容易地集成到Spring,属于轻量级框架。提供了包括认证、授权、加密、会话管理等功能。安全有时候是很复杂的,与Spring Security 相比,Shiro使用了比较简单易懂易于使用的授权方式。

官网:http://shiro.apache.org 

Shiro框架体系

  • Authentication(认证):用户身份识别,通常被称为用户“登录”。
  • Authorization(授权):访问控制。比如某个用户是否具有某个操作的使用权限。
  • Session Management(会话管理):特定于用户的会话管理,甚至在非web 应用程序。
  • Cryptography(加密):在对数据源使用加密算法加密的同时,保证易于使用。

三个概念

  • Subject:代表当前用户,可以是一个人,也可以是第三方服务。在单应用中,可将其视为User的同义词。
  • SecurityManager:管理所有Subject,对于 Web 应用一般使用DefaultWebSecurityManager。
  • Realms:用于进行权限信息的验证,我们自己实现。是一个执行者,负责真正的认证和鉴权。

我们需要实现Realms的Authentication 和 Authorization。其中 Authentication 是用来验证用户身份,Authorization是授权访问控制,用于对用户进行的操作授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。

Springboot集成


<!-- shiro -->

<dependency>

	<groupId>org.apache.shiro</groupId>

	<artifactId>shiro-spring</artifactId>

	<version>1.4.1</version>

</dependency>

自定义认证器MyShiroRealm

添加MyShiroRealm并继承AuthorizingRealm,实现其中的两个方法。
doGetAuthenticationInfo:实现用户认证,通过服务加载用户信息并构造认证对象返回。
doGetAuthorizationInfo:实现权限认证,通过服务加载用户角色和权限信息设置进去。


/**

 * 实现AuthorizingRealm接口用户用户认证

 */

public class MyShiroRealm extends AuthorizingRealm {



    @Autowired

    private LoginService loginService;



    /**

     * 用户认证

     */

    @Override

    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)

            throws AuthenticationException {

        // 加这一步的目的是在Post请求的时候会先进认证,然后在到请求

        if (authenticationToken.getPrincipal() == null) {

            return null;

        }

        // 获取用户信息

        String name = authenticationToken.getPrincipal().toString();

        User user = loginService.findByName(name);

        if (user == null) {

            // 这里返回后会报出对应异常

            return null;

        } else {

            // 这里验证authenticationToken和simpleAuthenticationInfo的信息

            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name,

                    user.getPassword().toString(), getName());

            return simpleAuthenticationInfo;

        }

    }



    /**

     * 角色权限和对应权限添加

     */

    @Override

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        // 获取登录用户名

        String name = (String) principalCollection.getPrimaryPrincipal();

        // 查询用户名称

        User user = loginService.findByName(name);

        // 添加角色和权限

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        for (Role role : user.getRoles()) {

            // 添加角色

            simpleAuthorizationInfo.addRole(role.getRoleName());

            for (Permission permission : role.getPermissions()) {

                // 添加权限

                simpleAuthorizationInfo.addStringPermission(permission.getPermission());

            }

        }

        return simpleAuthorizationInfo;

    }



}

添加Shiro配置类

配置路由的访问控制,以及注入自定义的认证器MyShiroRealm。


@Configuration

public class ShiroConfig {



    // 将自己的验证方式加入容器

    @Bean

    public MyShiroRealm myShiroRealm() {

        MyShiroRealm myShiroRealm = new MyShiroRealm();

        return myShiroRealm;

    }



    // 权限管理,配置主要是Realm的管理认证

    @Bean

    public SecurityManager securityManager() {

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        securityManager.setRealm(myShiroRealm());

        return securityManager;

    }



    // Filter工厂,设置对应的过滤条件和跳转条件

    @Bean

    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        shiroFilterFactoryBean.setSecurityManager(securityManager);

        Map<String, String> filterMap = new HashMap<String, String>();

        // 登出

        filterMap.put(/logout, logout);

        // swagger

        filterMap.put(/swagger**/**, anon);

        filterMap.put(/webjars/**, anon);

        filterMap.put(/v2/**, anon);

        // 对所有用户认证

        filterMap.put(/**, authc);

        // 登录

        shiroFilterFactoryBean.setLoginUrl(/login);

        // 首页

        shiroFilterFactoryBean.setSuccessUrl(/index);

        // 错误页面,认证不通过跳转

        shiroFilterFactoryBean.setUnauthorizedUrl(/error);

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        return shiroFilterFactoryBean;

    }



    // 加入注解的使用,不加入这个注解不生效

    @Bean

    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {

        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();

        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);

        return authorizationAttributeSourceAdvisor;

    }

}

LoginController


    /**

	 * POST登录

	 */

	@PostMapping(value = /login)

	public String login(@RequestBody User user) {

		// 添加用户认证信息

		UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getName(), user.getPassword());

		SecurityUtils.getSubject().login(usernamePasswordToken);

		return login ok!;

	}

一个简单的Shiro集成,已经完成了。其它User,Role,Dao比较基础的省略不占篇幅了。

启动springboot,提交/login接口username,password验证。

 

Linux 文件共享方案 Springboot集成Mybatis-plus
微信公众号