博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Starter方式实现Springboot与Shiro集成
阅读量:4045 次
发布时间:2019-05-24

本文共 8448 字,大约阅读时间需要 28 分钟。

Starter方式实现Springboot与Shiro集成

Apache Shiro是什么?

Apache Shiro是一个强大且易用的Java安全框架,能够执行身份验证、授权、加密和会话管理等。

Apache Shiro的主要API

Subject

Subject即“当前操作用户”。但是,在Shiro中,Subject这一概念并不是"帐户",而是与shrio交互的当前应用。

SecurityManager

SecurityManager是Shiro框架的核心,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

Realm

  • Realm是安全数据源,其中包含认证和授权数据。

    也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

  • 当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。

    Shiro内置了很多可用的安全数据源(又名目录)的Realm, 如果内置的Realm不能满足需求,可以自定义Realm实现。

Apache Shiro与Springboot集成

依赖引入

org.apache.shiro
shiro-spring-boot-web-starter
1.4.1

开发集成shiro的配置类

开发一个集成shiro的spring配置类

@Configurationpublic class ShiroConfigure {	private static final Logger LOG = LoggerFactory.getLogger(ShiroConfigure.class);    		//注册跨域过滤器	//开发和配置安全数据源		//配置shiro过滤器拦截规则定义		}

注册跨域过滤器

shiro过滤器会优先于springboot拦截请求,springboot的跨域设置将不起作用,因此需要专门注册跨域过滤器并设置其为过滤器链中的第一个。

@Bean    public FilterRegistrationBean
corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); // 允许cookies跨域 config.setAllowCredentials(true); // 允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin config.addAllowedOrigin("*"); // 允许访问的头信息,*表示全部 config.addAllowedHeader("*"); // 预检请求(options请求)的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 config.setMaxAge(1L); // 允许提交请求的方法,*表示全部允许 config.addAllowedMethod("*"); /* config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); */ //设置允许跨域的路径 source.registerCorsConfiguration("/**", config); FilterRegistrationBean
bean = new FilterRegistrationBean
(new CorsFilter(source)); // 设过滤器的优先级 bean.setOrder(0); return bean; }

开发和配置安全数据源

/*    *   配置安全数据源Realm    *   此处必须要命名“authorizer”,    *   因为shiro会自动寻找名称为“authorizer”的、并实现接口Authorizer的对象,    *   而AuthorizingRealm正是接口Authorizer的实现类    */    @Bean("authorizer")    @Autowired    public AuthorizingRealm saftyRealm(ShiroService shiroService) {                return new AuthorizingRealm() {            /**            * 获取当事人(当前用户)授权信息,shiro在检查访问是否经过授权时需要通过该方法获取授权信息。            * 参数PrincipalCollection 当事人集合            */	            @Override            protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {                /*                * 获取登录用户帐号                */                CurrUser currUser = (CurrUser) principalCollection.getPrimaryPrincipal();// 获取首要(第一)当事人                /*                * 创建授权信息对象                */                SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();                                                        /*                * 查询用户权限,并将权限放入授权信息对象中		                 */                List
moduleList = shiroService.getModulesOfUser(currUser.getUserId()); for (Module module : moduleList) { simpleAuthorizationInfo.addStringPermission(String.valueOf(module.getM_id())); } // System.out.println(currUser.getUserId()+"->"+simpleAuthorizationInfo.getStringPermissions()); /* * 返回授权信息 */ return simpleAuthorizationInfo; } /** * 获取认证信息(即包含当前用户帐户和合法密码等信息) * shiro在登录认证时需要通过该方法获取认证信息。 * 参数 AuthenticationToken 认证令牌(如:一组用户名和密码就是一个认证令牌) */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) { String userId = (String) token.getPrincipal();// 获得当事人(当前用户账号) User user = shiroService.getUser(userId); /* 如果不存在前用户信息,返回null */ if (user == null) { return null; } /* 创建当前用户 */ CurrUser currUser = new CurrUser(user.getU_id(),user.getU_name()); /* 创建认证信息,三个构造参数含义依次如下: 参数1:principal当前用户 参数2:credentials认证凭证(如:口令、密码等) 参数3:realm名称 */ SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(currUser, user.getU_pwd(), this.getName()); /* 返回认证信息 */ return info; } } ; }

配置shiro过滤器拦截规则定义

@Bean @Autowired    public ShiroFilterChainDefinition shiroFilterChainDefinition(ShiroService shiroService) {                DefaultShiroFilterChainDefinition chainDefinition =                                                     new DefaultShiroFilterChainDefinition();                    /*            可匿名访问资源        */        chainDefinition.addPathDefinition("/css/**", "anon");        chainDefinition.addPathDefinition("/elementui/**", "anon");        chainDefinition.addPathDefinition("/js/**", "anon");        chainDefinition.addPathDefinition("/safty/login/**", "anon");                        //加载动态权限         List
moduleList = shiroService.getAllSubModules(); String PREMISSION_FORMAT = "authc,perms[{0}]"; //动态权限设置 for(Module module:moduleList) { if(StringUtils.isEmpty(module.getM_url())) { continue; } chainDefinition.addPathDefinition(module.getM_url().replace("index.html", "**"), MessageFormat.format(PREMISSION_FORMAT, String.valueOf(module.getM_id()))); } //其它资源必须经过认证 chainDefinition.addPathDefinition("/**", "authc"); LOG.debug("=====Shiro安全规则======================================================================="); LOG.debug(chainDefinition.getFilterChainMap().toString()); LOG.debug("=====Shiro安全规则======================================================================="); return chainDefinition; } }

在配置文件application.yaml中配置shiro

shiro:  loginUrl: /loginTo #拦截需要认证而未认证的请求后的跳转路径  successUrl: /successTo #一种附加配置,session中没有存储登录成功后跳转的地址时起作用  unauthorizedUrl: /unauthorizedTo #拦截需要需要授权而未授权的请求后的跳转路径

登录示例

@RestController@RequestMapping("/safty/login")public class LoginController {		@Autowired	private LoginService loginService;		@PostMapping("/user")	public Result execLogin(@RequestBody UserDto userDto,HttpSession session) {		try {			Subject subject = SecurityUtils.getSubject();						//创建登录令牌			UsernamePasswordToken usernamePasswordToken = 					new UsernamePasswordToken(userDto.getU_id(),userDto.getU_pwd());						//登录,该方法声明抛出异常,可以捕获异常,并进行应对处理			subject.login(usernamePasswordToken);						//是否通过认证			if(subject.isAuthenticated()) {								//获得当前用户信息				CurrUser currUser = (CurrUser)subject.getPrincipal();								//将当前用户放入Session。注:这里的Session是由Shiro提供的。				subject.getSession().setAttribute(Constants.SESSINON_ATTR_NAME_CURR_USER, currUser);												return Result.successResult("登录成功!");			}						return Result.failResult("登录失败!");					} catch (UnknownAccountException e) {			return Result.failResult("用户名不存在!");	    		    } catch (IncorrectCredentialsException e) {	    	return Result.failResult("账户密码不正确!");	    } catch (LockedAccountException e) {	    	return Result.failResult("用户名被锁定 !");	    }catch (Exception e) {			e.printStackTrace();			return Result.failResult("系统错误!");		}			}}

退出示例

@RestController@RequestMapping("/safty/logout")public class LoginController {		@Autowired	private LoginService loginService;			@DeleteMapping("/logout")	public ResultDto login_authentication() {				try {			//注销			SecurityUtils.getSubject().logout();			return Result.successResult();		} catch (Exception e) {			return Result.failResult("退出失败!");		}	}}

测试

上述配置和相关代码开发完成后,即可进行测试调试。

附录:某shiro应用案例具体内容

  1. 开发安全数据源获取数据的和(含)

  2. 开发

  3. 开发或修改、等涉及当前用户的控制器

  4. 在中添加如下配置:

    shiro.loginUrl=/loginTo shiro.successUrl=/successTo shiro.unauthorizedUrl=/unauthorizedTo
  5. 开发shiro.loginUrl=/loginTo、shiro.successUrl=/successTo和shiro.unauthorizedUrl=/unauthorizedTo三个配置中的。

  6. 前端处理请参阅

转载地址:http://bihdi.baihongyu.com/

你可能感兴趣的文章
Linux系统信息查看
查看>>
用find命令查找最近修改过的文件
查看>>
Android2.1消息应用(Messaging)源码学习笔记
查看>>
android raw读取超过1M文件的方法
查看>>
ubuntu下SVN服务器安装配置
查看>>
MPMoviePlayerViewController和MPMoviePlayerController的使用
查看>>
CocoaPods实践之制作篇
查看>>
[Mac]Mac 操作系统 常见技巧
查看>>
苹果Swift编程语言入门教程【中文版】
查看>>
捕鱼忍者(ninja fishing)之游戏指南+游戏攻略+游戏体验
查看>>
iphone开发基础之objective-c学习
查看>>
iphone开发之SDK研究(待续)
查看>>
计算机网络复习要点
查看>>
Variable property attributes or Modifiers in iOS
查看>>
NSNotificationCenter 用法总结
查看>>
C primer plus 基础总结(一)
查看>>
剑指offer算法题分析与整理(三)
查看>>
Ubuntu 13.10使用fcitx输入法
查看>>
pidgin-lwqq 安装
查看>>
mint/ubuntu安装搜狗输入法
查看>>