shiro实现登录验证

思路:
客户端传递用户名和密码到控制层,控制层接收到用户名和密码之后交给一个UsernamePasswordToken对象进行处理,并且用MD5对密码进行加密处理(我们这里是封装了个MD5Utils). 创建一个subject对象(subject 可以理解为用户)。
调用subject类的login 方法 把UsernamePasswordTken对象交给securityManager 管理
我的理解是securityManager 会调用自定义的域(也可以理解为真正处理验证 和授权等业务的具体类这个类需要继承AuthorizingRealm抽象 类)来具体处理验证业务

          实现授权doGetAuthorizationInfo 方法 
               验证doGetAuthenticationInfo方法

下面是 springboot项目实现登录验证的具体流程
引入依赖
1.
org.apache.shiro
shiro-core
1.3.2


org.apache.shiro
shiro-spring
1.3.2

2.controller层代码
@RequestMapping(“loginSign”)
@ResponseBody
//客户端传递用户名和密码到控制层
public R loginSign(String username,String password){

    ****//  stringUtils方法时String提供的工具类调用它的isBland方法判断用户名是否为空如果为空就****
    if(StringUtils.isBlank(username)){
        return R.error("用户名不能为空");
    }
    if(StringUtils.isBlank(password)){
        return R.error("密码不能为空");
    }
    //认证创建一个subject对象
    org.apache.shiro.subject.Subject subject = SecurityUtils.getSubject();
     //UsernamePasswordToken 是AuthenticationToken的子类
    UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username, MD5Utils.encrypt(password));
    try {
        //调用subject对象的login方法
        subject.login(usernamePasswordToken);
    }catch (UnknownAccountException e) {
          //如果用户名不正确就走这个异常
        return  R.error("未查询到该用户");
    }catch(LockedAccountException e){
        return R.error("用户认证失败");
    }catch(Exception e){
        return  R.error("登录失败");
    }
    return R.ok();
}

3.自定义一个域
**
//加入这个注解是把这个类交给spring 管理
@Component
//继承AuthorizingRealm类
public class MyRealm extends AuthorizingRealm {

//注入一个业务层
@Autowired
UserService userService;
//授权方法处理授权业务
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}

//认证方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//因为看UsernamePassword是AuthenticationToken的子类 所以这里可以得到UsernamePasswordToken根据用户名 去数据库 查用户
UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken;
//这里获取的是客户端传过来的用户名和密码
String userName=token.getUsername();
//对传过来的密码进行加密
String password= new String(token.getPassword());
//根据用户名查询一个对象
SysUser user=userService.findByUserName(userName);
//使用抛异常的方式进行验证
if(user==null){
//没有查询到用户就抛出异常
throw new UnknownAccountException();

    }
    if(!user.getPassword().equals(password)){
       //密码不正确
        throw new AccountException();

    }

    if(Constant.UserStuatus==user.getStatus()){
       //禁用状态
        throw new LockedAccountException();
    }
    //登录成功后将用户交给shiro 处理 getName()是当前域的名称
    SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(user,user.getPassword(),getName());

//返回simpleAuthenticationInfo对象
return simpleAuthenticationInfo;
}
}

4.定义个配置类
//这个注解将 此类标示为配置类
@Configuration
public class ShiroConfig {
/**
* 配置shiro 过滤器用于过滤路径 哪些是需要拦截的哪些是需要放行的
* @return
/
@Bean
ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);//过滤器 实现核心管理器
shiroFilterFactoryBean.setLoginUrl("/login");//登录页面路径
shiroFilterFactoryBean.setSuccessUrl("/index");//系统登录成功后的首页
shiroFilterFactoryBean.setUnauthorizedUrl("/403");//没有权限之后的跳转路径
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login",“anon”); //不拦截
filterChainDefinitionMap.put("/css/", “anon”); //不拦截
filterChainDefinitionMap.put("/js/
", “anon”); //不拦截
filterChainDefinitionMap.put("/fonts/", “anon”);//不拦截
filterChainDefinitionMap.put("/img/
", “anon”); //不拦截
filterChainDefinitionMap.put("/druid/", “anon”);//不拦截
filterChainDefinitionMap.put("/upload/
", “anon”);//不拦截
filterChainDefinitionMap.put("/files/", “anon”);//不拦截
filterChainDefinitionMap.put("/logout", “logout”);//不拦截
filterChainDefinitionMap.put("/loginSign", “anon”);//不拦截
filterChainDefinitionMap.put("/", “anon”);//不拦截
filterChainDefinitionMap.put("/
", “authc”);//除上面路径外 全拦截
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/
*
* ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
* @return
/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
/
*
* 配置核心管理控制器用的是注入的方式
* @return
*/
@Bean
SecurityManager securityManager(){

//创建securityManager对象
    DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
    
    //把自定义的域赋值给securityManager对象
    defaultWebSecurityManager.setRealm(myRealm());
    return defaultWebSecurityManager;
}

/**
 * 定义自定义的域  域中写了 认证的方法   授权的方法
 * @return
 */
@Bean
MyRealm myRealm(){
    MyRealm myRealm = new MyRealm();
    return myRealm;
}

/**
 * 管理shiro一些bean的生命周期。
 * @return
 */
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
}
/**
 * 开启shiro aop注解支持.
 * 使用代理方式;所以需要开启代码支持;
 * @param securityManager
 * @return
 */
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    return authorizationAttributeSourceAdvisor;
}

}

猜你喜欢

转载自blog.csdn.net/weixin_43848065/article/details/85345274