shiro的前后的分离的使用(SpringBoot)

一、Shiro核心组件

shiro的前后的分离的使用(SpringBoot)_第1张图片

shiro的运行机制

shiro的前后的分离的使用(SpringBoot)_第2张图片

一、Shiro实现登录认证()

       1.首先继承 AuthorizingRealm 类,用于实现登录和认证

        分别实现两个方法

doGetAuthorizationInfo        //用于授权

doGetAuthenticationInfo       //用于认证

        2.首先需要封装用户的信息,因为用户名和密码已经传进来了,并且封装到了方法参数AuthenticationToken  中的  authenticationToken  内部,所以要获取用户的信息,比如账号和密码,就需要获取  UsernamePasswordToken  的Token。

        3.获取Token之后然后取得Token中用户的用户名,从数据库查询用户的信息并返回。拿到用户的信息之后判断用户是否存在。

        4.如果数据库查询的对象不为空:验证完用户存在之后,要验证密码就需要创建  SimpleAuthenticationInfo  的对象,并把数据库查询到的用户user,用户的密码user.getPassword()和getName()传进参数位置中。最后把创建的SimpleAuthenticationInfo  对象返回。        

        5.SimpleAuthenticationInfo 是把传进来的用户数据,即Token获得的密码和数据库获得的密码进行对比来判断密码是否正确。

        6.如果数据库查询的对象为空:则返回null。

 /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
        User user = userService.selectByUserName(usernamePasswordToken.getUsername());
        if(user!=null){
            return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
        }
        return null;
    }

二、  Shiro配置类的配置

       1. 配置安全管理器,开发者自定义的Realm需要注入进 DefaultWebSecurityManager进行管理才能生效。

       2. 自定义的UserRealm

     

​
package com.realm;

import com.domain.User;
import com.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;
@Component
public class UserRealm extends AuthorizingRealm{


    @Autowired
    private UserService userService;
    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        Set roles=new HashSet<>();
        roles.add(user.getUsername());
        SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();

        return null;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
        User user = userService.selectByUserName(usernamePasswordToken.getUsername());
        if(user!=null){
            return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
        }
        return null;
    }
}

​

          3.注入自定义的Realm

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

        4.创建安全管理器,并将自定义的UserRealm注入管理器中

                使用 @Qualifier (" userRealm ") 注释可根据名称注入方法中

@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
    DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
    manager.setRealm(userRealm);
    return manager;
}

        5.创建过滤器工厂

                注入安全管理器  DefaultWebSecurityManager 

                其中的编写认证和授权规则

shiro的前后的分离的使用(SpringBoot)_第3张图片

                      创建过滤器工厂ShiroFilterFactoryBean并在过滤器工厂中设置安全管理器

ShiroFilterFactoryBean factoryBean=new ShiroFilterFactoryBean();    //创建过滤器工厂
factoryBean.setSecurityManager(defaultWebSecurityManager);  //设置

                进行权限设置 

Map map=new HashMap<>();
map.put("/student/menu","authc");
factoryBean.setFilterChainDefinitionMap(map);   //设置拦截的地址和认证过滤器
factoryBean.setLoginUrl("/user/entry");     //设置允许访问的地址用来登录

                最终代码

package com.config;

import com.realm.UserRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    /**
     *
     * @return
     */
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    /**
     *
     * @param userRealm
     * @return
     */
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager manager=new DefaultWebSecurityManager();
        manager.setRealm(userRealm);
        return manager;
    }

    /**
     *authc登陆验证
     * anon无需登录
     * @param defaultWebSecurityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean factoryBean=new ShiroFilterFactoryBean();    //创建过滤器工厂
        factoryBean.setSecurityManager(defaultWebSecurityManager);  //设置
        Map map=new HashMap<>();
        map.put("/student/menu","authc");
        factoryBean.setFilterChainDefinitionMap(map);   //设置拦截的地址和认证过滤器
        factoryBean.setLoginUrl("/user/entry");     //设置允许访问的地址用来登录
        return factoryBean;
    }
}

三、在Controller层进行配置

                

@RequestMapping("/login")
    @ResponseBody
    public R login(User user,HttpServletRequest request){
        Subject subject = SecurityUtils.getSubject();//获取用户的信息
        String tmppassword=user.getPassword();  //进行加密,保证密码验证成功,因为数据库存储的密码已MD5加密
        tmppassword=DigestUtils.md5DigestAsHex(tmppassword.getBytes());
        UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(),tmppassword);//使用用户信息创建Token令牌
        try {
            subject.login(token);//将生成的Token用于身份验证,跳转AuthenticationInfo认证,进行认证
            User userPrincipal = (User) subject.getPrincipal();
            request.getSession().setAttribute("account",user.getUsername());
            return R.success("登陆成功");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            return R.error("账号不存在");
        } catch(IncorrectCredentialsException e){
            e.printStackTrace();
            return R.error("密码错误");
        }

    }

四、Shiro实现授权

        

/**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取当前用户信息
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        //设置角色
        Set roles=new HashSet<>();
        roles.add(user.getUsername());
        //设置权限
        SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();

        return authorizationInfo;
    }

        总代码

package com.realm;

import com.domain.User;
import com.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;
@Component
public class UserRealm extends AuthorizingRealm{


    @Autowired
    private UserService userService;
    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取当前用户信息
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        //设置角色
        Set roles=new HashSet<>();
        roles.add(user.getUsername());
        //设置权限
        SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();

        return authorizationInfo;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken;
        User user = userService.selectByUserName(usernamePasswordToken.getUsername());
        if(user!=null){
            return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
        }
        return null;
    }
}

五、退出

        Controller层创建Logout

        

@RequestMapping("/logout")
    @ResponseBody
    public R logout(){
        Subject subject = SecurityUtils.getSubject();//获取用户信息
        subject.logout();//取消认证和授权
        return R.success("退出");
    }

        如果退出则调用该接口,则实现认证取消

你可能感兴趣的:(spring,boot,java,后端)