[spring-boot] 集成shiro

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/crazyman2010/article/details/76038838

shiro介绍

shiro是一个权限管理框架,基于用户-角色-权限。一个用户可以有多个角色,一个角色有多个权限,每个权限指定了资源的访问。
shiro的原理是在所有请求之前设置一个filter,这个filter判断哪些资源需要权限,哪些不要,对于不需要权限的直接放行,对于需要权限的,使用securityManager和realm进行身份验证和授权,如果验证失败或者权限不足,都跳转到登录页面或者返回错误信息。这和我们自己使用账号密码判断是一样的,只是这个框架让我们少写很多代码。
spring-boot 集成shiro其实相当简单。

加入依赖

//shiro
compile group: 'org.apache.shiro', name: 'shiro-spring', version: '1.4.0'

ShiroConfig

建立一个配置文件,用来配置shiro

package com.example.shiro;

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

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

/**
 * Shiro 配置
 */
@Configuration
public class ShiroConfig {
    //创建shiroFilterFactoryBean, 设置securityManager、配置filterChain
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean createShiroFilterFactoryBean() {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(createSecurityManager());
        bean.setLoginUrl("/admin/web/login"); //登录页面

        Map<String, String> filterChainMap = new LinkedHashMap<>(); //这里一定要是有序的
        //这里可以从数据库中读取权限-资源规则
        filterChainMap.put("/api/v1/admin/login", "anon"); //登录不需要验证权限
        filterChainMap.put("/api/v1/admin/**", "authc"); //其他api需要权限
        filterChainMap.put("/admin/web/login", "anon");//登录页面不需要权限
        filterChainMap.put("/admin/web/**", "authc");//其他页面需要权限
        bean.setFilterChainDefinitionMap(filterChainMap);
        return bean;
    }

    //创建一个securityManager
    @Bean(name = "securityManager")
    public SecurityManager createSecurityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager(new UserRealm());
        return manager;
    }
}

创建realm

realm 主要用来验证密码和授权

@Component
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;

    @Override
    public String getName() {
        return "user-realm";
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return true;
    }

    //获取用户的验证信息,用于和token进行对比
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String userName = (String) token.getPrincipal();
        User user = userService.findUserByAccount(userName);
        if (user == null) {
            return null;
        }
        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }


    //给用户设置角色信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        User user = (User) principals.getPrimaryPrincipal();
        Set<String> roles=new HashSet<>();
        roles.add(user.getRole());
        return new SimpleAuthorizationInfo(roles);
    }

    //设置权限信息
    @Override
    protected Collection<Permission> getPermissions(AuthorizationInfo info) {
        return super.getPermissions(info);
    }
}

登录

@PostMapping("/login")
    @ResponseBody
    public DtoWrap login(@RequestBody UserDto userDto) {
        DtoWrap result = new DtoWrap();
        Subject subject = SecurityUtils.getSubject();
        AuthenticationToken token = new UsernamePasswordToken(userDto.getUserName(), userDto.getPassword());
        try {
            subject.login(token);
            //if no exception, that's it, we're done!
        } catch (AuthenticationException ae) {
            throw new BusinessException("用户名或密码错误");
        }
        return result;
    }

猜你喜欢

转载自blog.csdn.net/crazyman2010/article/details/76038838