关于shiro:Shiro的使用之认证拦截

52次阅读

共计 4768 个字符,预计需要花费 12 分钟才能阅读完成。

Shiro 的应用之认证拦挡

    Shiro 是一个平安开发框架,它把零碎的平安认证等相干性能抽取进去,升高了零碎的开发成本。

一 Shiro 实现认证拦挡

    步骤: 1 零碎调用 subject 的 login 办法将用户信息传递给 securityManager
          2 securityManager 将认证操作委托给 Authenticator
          3 Authenticator 将用户输出的身份信息发送给 Realm
          4 Realm 拜访数据库获取用户信息并将信息封装并返回
          5 Authenticator 对封装的信息进行身份认证
          


输出用户信息后登陆到零碎界面


1. 须要的依赖
<dependency>
     <groupId>org.apache.shiro</groupId>
     <artifactId>shiro-spring</artifactId>
     <version>1.5.3</version>
</dependency>
2. Shiro 的外围配置对象

在 springboot 中没有为咱们主动配置 shiro,所以要手动配置

  • 首先创立一个配置类:SpringShiroConfig 类;
  • 而后在配置类中增加 SecurityManager 接口对象;
  • 在配置类中增加一个 ShiroFilterFactoryBean 对象;通过此对象实现对匿名拜访和认证拜访
  • 代码如下:
package com.py.pj.common.config;

import java.util.LinkedHashMap;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
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;

/**
 * @author WL
 * @version 创立工夫:2020-9-19 13:24:57
 * @Description Shiro 的外围配置对象
 * @Configuration 此注解形容的类是一个配置对象,此对象会交给 spring 解决
 * @Bean 此注解形容的类会被交给 spring 解决,由 spring 为咱们创建对象
 */
@Configuration
public class SpringShiroConfig {

    
    @Bean
    public SecurityManager securityManager(Realm realm) {DefaultWebSecurityManager dsm = new DefaultWebSecurityManager();
        dsm.setRealm(realm);
        return dsm;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {ShiroFilterFactoryBean sffBean = new ShiroFilterFactoryBean();
        sffBean.setSecurityManager(securityManager);
          //  设置登录界面 url
        sffBean.setLoginUrl("/doLogin");
        
        LinkedHashMap<String, String> map = new LinkedHashMap<>();

        map.put("/bower_components/**", "anon");
        map.put("/modules/**", "anon");
        map.put("/dist/**", "anon");
        map.put("/plugins/**", "anon");

        // 用户登录界面容许匿名拜访
        map.put("/user/doLogin", "anon");
        //  退出登陆
        map.put("/doLogout", "logout");
        
        // 除了动态资源,其余的都要认证
        map.put("/**", "authc");

        sffBean.setFilterChainDefinitionMap(map);
        return sffBean;
    }
}
3. 业务模块实现
    本模块的业务在 realm 模块中实现 
  • 3.1 依据用户名搜寻用户信息

在 SysUserMapper 中创立 findUserByUsername(String username) 办法

SysUser findUserByUsername(String username);


mapper 映射文件中
<select id="findUserByUsername" resultType="com.py.pj.sys.entity.SysUser">
    select * from sys_users where username=#{username}
</select>
  • 3.2 创立 realm 业务层
package com.py.pj.sys.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.py.pj.sys.dao.SysUserMapper;
import com.py.pj.sys.entity.SysUser;

/**
 * @author WL
 * @version 创立工夫:2020-9-19 14:15:12
 * @Description 受权 realm 继承认证,所以蕴含认证和受权性能
 */
@Service
public class ShiroUserRealm extends AuthorizingRealm {

    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 设置凭证匹配器匹配规定
     */

    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        // 创立凭证匹配器对象
        HashedCredentialsMatcher hcm = new HashedCredentialsMatcher();
        // 设置加密算法,与用户明码加密算法放弃始终
        hcm.setHashAlgorithmName("MD5");
        // 设置加密次数
        hcm.setHashIterations(1);
        super.setCredentialsMatcher(hcm);
    }

    /**
     * 受权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * 重写认证 token 是从客户端传来的用户的账号信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 1. 获取用户输出的用户名
        UsernamePasswordToken UToken = (UsernamePasswordToken) token;
        String username = UToken.getUsername();
        // 2. 基于用户名查用户信息
        SysUser user = sysUserMapper.findUserByUsername(username);
        // 3. 判断用户是否存在、是否禁用
        if (user == null) {throw new UnknownAccountException();
        }
        if (user.getValid() == 0) {throw new LockedAccountException();
        }
        // 4. 封装用户信息
        // 盐值是 ByteSource 格局的所以要转换
        ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());

        System.out.println(user.getPassword());
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, // principal ( 身份)
                user.getPassword(), // hashedCredentials
                credentialsSalt, // credentialsSalt
                getName());// realName

        return info;
    }

}

  • 3.3 controller 层
    
    @RequestMapping("doLogin")
    public JsonResult doLogin(String username,String password) {
        //    每个用户都是一个 subject 对象
        Subject subject = SecurityUtils.getSubject();
        //    对用户进行封装
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        //    token 被传给 securityManager;securityManager 在传递给 Authentication;Authentication 再传给 realm,从数据库中获取并封装用户信息
        subject.login(token);
        return new JsonResult("OK");
    }

至此,借助 Shiro 实现了用户的登陆认证性能。

正文完
 0