SpringBoot 整合Shiro 实现身份权限验证

SpringBoot 整合Shiro 实现身份权限验证

具体代码访问链接下载

从项目到部署服务器的过程,毕竟些写项目是为了发布部署服务器。
本篇主要介绍**SpringBoot 整合Shiro 实现身份权限验证**
  

原理:

1.没有登录情况:访问api接口--->shiro配置拦截——->跳转到shiro配置的setLoginUrl(“”)接口

2.去登陆【前提设置开放登陆接口filterChainDefinitionMap.put("/login", "anon");,不然会被拦截,走步骤1】:
	访问登录接口---》进入登录接口处理参数,内部调用subject.login(token)
	-----》进入shrio的身份验证方法doGetAuthenticationInfo
	-------》通过之后返回登录接口继续之后方法,返回前端

3.登录情况访问api接口:
	访问api接口--->shiro配置拦截——->
	跳转到shiro的权限验证方法doGetAuthorizationInfo--------》
	【不通过跳转到shiro配置的	shiroFilterFactoryBean.setUnauthorizedUrl("/noPermission");】
	通过之后进入真正的api接口,返回前端


步骤:


1. springboot的pom文件添加依赖,导入sql.位置在资源目录下

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

1.1配置ShiroConfig

@Configuration
public class ShiroConfig {
	@Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		// 必须设置 SecurityManager
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
		shiroFilterFactoryBean.setLoginUrl("/notLogin");
		// 设置无权限时跳转的 url;
		shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");

		// 设置拦截器
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
		//游客,开发权限
		filterChainDefinitionMap.put("/guest/**", "anon");
		//用户,需要角色权限 “user”
		filterChainDefinitionMap.put("/user/**", "roles[user]");
		//管理员,需要角色权限 “admin”
		filterChainDefinitionMap.put("/admin/**", "roles[admin]");
		//开放登陆接口
		filterChainDefinitionMap.put("/login", "anon");
		//其余接口一律拦截
		//主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截
		filterChainDefinitionMap.put("/**", "authc");

		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		System.out.println("Shiro拦截器工厂类注入成功");
		return shiroFilterFactoryBean;
	}

	/**
	 * 注入 securityManager
	 */
	@Bean
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		// 设置realm.
		securityManager.setRealm(customRealm());
		return securityManager;
	}

	/**
	 * 自定义身份认证 realm;
	 * <p>
	 * 必须写这个类,并加上 @Bean 注解,目的是注入 CustomRealm,
	 * 否则会影响 CustomRealm类 中其他类的依赖注入
	 */
	@Bean
	public MyShiroRealm customRealm() {
		return new MyShiroRealm();
	}

2.配置MyShiroRealm

public class MyShiroRealm extends AuthorizingRealm {
    private UserInfoService userInfoService;

    @Autowired
    private void setUserMapper(UserInfoService userInfoService) {
        this.userInfoService = userInfoService;
    }

    /**
     * 获取身份验证信息
     * Shiro中,最终是通过 Realm 来获取应用程序中的用户、角色及权限信息的。
     *
     * @param authenticationToken 用户身份信息 token
     * @return 返回封装了用户信息的 AuthenticationInfo 实例
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("————身份认证方法————");
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        // 从数据库获取对应用户名密码的用户
        String password = userInfoService.getPassword(token.getUsername());
        if (null == password) {
            throw new AccountException("用户名不正确");
        } else if (!password.equals(new String((char[]) token.getCredentials()))) {
            throw new AccountException("密码不正确");
        }
        return new SimpleAuthenticationInfo(token.getPrincipal(), password, getName());
    }

    /**
     * 获取授权信息
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("————权限认证————");
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获得该用户角色
        String role = userInfoService.getRole(username);
        Set<String> set = new HashSet<>();
        //需要将 role 封装到 Set 作为 info.setRoles() 的参数
        set.add(role);
        //设置该用户拥有的角色
        info.setRoles(set);
        return info;
    }

}

3.登录方法

@RestController
public class LoginController {
    @Autowired
    private UserInfoService userInfoService;
    private Logger logger = LoggerFactory.getLogger(LoginController.class);

    @RequestMapping(value = "/notLogin", method = RequestMethod.GET)
    public ResultMap notLogin() {
        return ResultMap.success().message("您尚未登陆!");
    }

    @RequestMapping(value = "/notRole", method = RequestMethod.GET)
    public ResultMap notRole() {
        return ResultMap.success().message("您没有权限!");
    }

    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public ResultMap logout() {
        Subject subject = SecurityUtils.getSubject();
        //注销
        subject.logout();
        return ResultMap.success().message("成功注销!");
    }

    /**
     * 登陆
     *
     * @param username 用户名
     * @param password 密码
     */
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ResultMap login(String username, String password) {
        logger.info("登陆-----------------------start");

        try {
            // 从SecurityUtils里边创建一个 subject
            Subject subject = SecurityUtils.getSubject();
            // 在认证提交前准备 token(令牌)
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            // 执行认证登陆
            subject.login(token);
            //根据权限,指定返回数据
            String role = userInfoService.getRole(username);
            if ("user".equals(role)) {
                return ResultMap.success().message("欢迎登陆");
            }
            if ("admin".equals(role)) {
                return ResultMap.success().message("欢迎来到管理员页面");
            }

        }catch (Exception e) {
        logger.error("登录失败,系统异常,异常信息为:{}", e);
        e.printStackTrace();
        return ResultMap.fail().message("登录失败,系统异常,异常信息为:{}"+e);
    }
        logger.info("登陆-----------------------end");
        return ResultMap.fail().message("权限错误!");
    }
}

参考文档《https://www.cnblogs.com/HowieYuan/p/9259638.html》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值