Shiro用户验证模块核心API分析(一)

——.用户验证核心模块简介

Subject :项目主体(关联SecurityManager)

SecurityManager :Shiro的的安全管理器(关联Realm)

Realm: Shiro访问数据库的桥梁

一。SpingBoot整合Shiro:

首先在Pom文件里导入Shiro的包。

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

第二步编写Shiro配置类

在配置之前我们先要编写一个自定义的Realm类。因为Realm是连接数据库的桥梁,Shiro会通过Realm来完成对用户权限和角色校验的逻辑。(这里暂时只编写用户授权逻辑)

package com.hukaihan.springbootshiro.shiro.config;


import com.hukaihan.springbootshiro.entity.User;
import com.hukaihan.springbootshiro.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
//执行授权逻辑
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权逻辑");
        return null;
    }
//执行认证逻辑
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行认证逻辑");
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        User byName = userService.findByName(usernamePasswordToken.getUsername());
        if(byName==null){
            //返回null会抛出一个UnknownAccountException
            return null;
        }
        //注意:不用自己判断只需返回一个AuthenticationInfo的子类,这里返回的是数据库中用户的密码
        return new SimpleAuthenticationInfo("",byName.getPassword(),"");

    }
}

上面的代码你可能不明白什么意思,但是不急,先往下看
由于Shiro框架的核心就是由过滤器Filter实现的,所以我要配置一个ShiroFilterFactoryBean(shiro内置的过滤器,实现用户权限角色拦截控制).

package com.hukaihan.springbootshiro.shiro.config;

import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.ShiroFilter;
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 {

    /**
     * 设置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultSecurityManager") DefaultWebSecurityManager defaultSecurityManager){
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(defaultSecurityManager);
        Map<String,String> map = new LinkedHashMap<String,String>();
        map.put("/delete","authc");
        map.put("/update","authc");
        /**
         * Shiro常用过滤器
         *  可以实现相关权限的拦截:
         *      anon:无需登陆认证
         *      authc:需要进行登陆认证才能访问的资源
         *      user:如果使用rememberMe的功能无需登录就可以直接访问
         *      perms:该资源必须得到相关权限才可以访问
         *      role:该资源必须得到角色资源才可以访问
         */

        shiroFilter.setFilterChainDefinitionMap(map);
        shiroFilter.setLoginUrl("/login");
        return shiroFilter;
    }
    /**
     * 创建defaultWebSecurityManager
     * @return
     */
    @Bean
    public DefaultWebSecurityManager defaultSecurityManager(@Qualifier("myRealm") UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //关联Realm对象
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
    }
    /**
     * 将UserRealm类加入spring
     * @return
     */

    @Bean
    public UserRealm myRealm(){
        return  new UserRealm();
    }
}

显然,这个过滤器依赖于一个SecurityManager,SecurityManager又依赖我们刚才写的Realm,一一配置好就可以了。

注意:

Shiro常用过滤器
* 可以实现相关权限的拦截:
* anon:无需登陆认证
* authc:需要进行登陆认证才能访问的资源
* user:如果使用rememberMe的功能无需登录就可以直接访问
* perms:该资源必须得到相关权限才可以访问
* role:该资源必须得到角色资源才可以访问

	编写好过滤器以后,就会帮我们拦截我们配置的路径,根据上面的参数。拦截后默认会去ogin.jsp,所以我们在这里配置一下,把它配成我们需要的.login.html。

然后编写登陆方法:

@GetMapping("/dologin")
    public String dologin(String uname,String pwd){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(uname,pwd);
        try {
            subject.login(usernamePasswordToken);
            return "/index";
        }catch (UnknownAccountException ex){
            //登录失败,密码错误
            System.out.println("用户名不存在");
            return "/login";
        }
        catch (IncorrectCredentialsException ex){
            //登录失败,密码错误
            System.out.println("密码错误");
            return "/login";
        }
    }
首先使用SecurityUtils帮我们生成一个Subject对象,也就是项目本体(我是这么理解的,不知道对不对哈哈,至少翻译的没错)。
将前台传来的用户名密码放在UsernamePasswordToken(用户令牌) 中,当然你还可以加验证码,不过要集成这个类加上验证码这个属性。
调用 subject.login(usernamePasswordToken);
之后他会去Realm类中执行我们编写的认证逻辑。

注意这个方法会抛出两个异常~:

UnknownAccountException:当用户名不存在时
IncorrectCredentialsException:密码错误时
这是你就可以回看我们之前写的Realm类了。当用户不存在时,返回一个null。这时Shiro就会帮我们抛出这个异常了。

成功就会返回到主页。至此简单的用户认证就做完了~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值