一、参数验证(@Validated、@Valid)
参数合法性校验:利用注解代替if判断,主要使用两种方法:
- 接受参数的实体类中加@NotNull(message = “xx不能为空!”);方法参数前面加@Valid。
- service或controller层入口加@Validated;方法参数上加@NotNull(message = “xx不能为空!”),注意不能加@RequestParam注解,不然参数没有传的情况下无法判断,因为该注解会去找是不是有参数,找不到就报错。
- 除了@NotNull,@NotEmpty,@NotBlank。还有其他用法:
@javax.validation.constraints.Pattern(
regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9_]+$",
message = "该账号包含了非法字符,请重新输入!")
@Length(min = 2, max = 32, message = "请输入2~32位字符")
二、jpa模糊查询
主要是两种:
1)controller层:一定要加 “%”+name+"%"
dao层: 一定要使用 JPA 规定的形式 findBy+参数名+Like(参数)
2)自己写sql语句:
@Query(value = “select t from Team t where t.name like %?1%”)
三、shiro
1)作用:shiro安全框架我们主要用于:
Authentication:用户认证(登录)
Authorization:权限控制
Session Management:会话管理
Cryptography:数据加密。
2)核心:
subject:用户主体(把操作交给securityManager)
securityManager:安全管理器(关联realm)
reaml:shiro连接数据的桥梁
Subject:Subject实质上是一个当前执行用户的特定的安全“视图”,开发者所写的应用代码就通过Subject与Shiro框架进行交互。所有Subject实例都必须绑定到一个SecurityManager上,当使用一个Subject实例时,Subject实例会和SecurityManager进行交互,完成相应操作。
SecurityManager:SecurityManager是Shiro的核心部分,作为一种“保护伞”对象来协调内部安全组件共同构成一个对象图。开发人员并不直接操作SecurityManager,而是通过Subject来操作SecurityManager来完成各种安全相关操作。
Realms:Realms担当Shiro和应用程序的安全数据之间的“桥梁”或“连接器”。从本质来讲,Realm是一个特定安全的DAO,Realm中封装了数据操作的模块和用户自定义的认证匹配过程。SecurityManager可能配置多个Realms,但至少要有一个。
3)springboot整合shiro:
- pom.xml导入shiro与spring整合依赖;
- 自定义realm类,继承AuthorizingRealm;
- 编写shiro配置类
创建ShiroFilterFactoryBean
创建SecurityManager(权限管理,配置主要是Realm的管理认证)
创建Realm,刚刚自定义的Realm加入容器
在ShiroFilterFactoryBean里添加shiro内置过滤器:
//常用的过滤器:
//anon:无需认证(登陆)可以访问
//authc:必须认证才可以访问
//user:如果使用rememberMe的功能可以直接访问
//perms:该资源必须得到资源权限才可以访问
//role:该资源必须得到角色权限才可以访问
Map<String,String> filterMap = new LinkedHashMap<String,String>();
filterMap.put("/testThymeleaf", "anon"); //放行
filterMap.put("/*", "authc"); //拦截
//修改跳转到的登陆页面,默认是跳到login.jsp
shiroFilterFactoryBean.setLoginUrl("/tologin");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
- 控制层中使用shiro编写认证操作
//获取subject
Subject subject = SecurityUtils.getSubject();
//封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//执行登陆方法
try {
// 进行验证,这里可以捕获异常,然后返回对应信息
subject.login(token);
} catch (UnknownAccountException e) {
log.error("用户名不存在!", e);
} catch (IncorrectCredentialsException e) {
log.error("账号或密码错误!", e);
} catch (UnauthorizedException e) {
log.error("没有权限!", e);
} catch (AuthorizationException e) {
log.error("没有权限!", e);
}
4)shiro权限控制的3种方式:
预热:Shiro授权的内部处理机制
1、在应用程序中调用授权验证方法(Subject的isPermitted*或hasRole*等)
2、Sbuject会委托应用程序设置的securityManager实例调用相应的isPermitted*或hasRole*方法。
3、接下来SecurityManager会委托内置的Authorizer的实例(默认是ModularRealmAuthorizer类的实例,类似认证实例)调用相应的授权方法。
4、每一个Realm将检查是否实现了相同的Authorizer 接口。然后,将调用Reaml自己的相应的授权验证方法。
- 基于代码实现权限管理:
Subject currentUser = SecurityUtils.getSubject();
if (currentUser.hasRole("administrator")) {
//拥有角色administrator
} else {
//没有角色处理
}
- jsp端,权限的处理
引入:
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>
body里:
<shiro:hasRole name="admin">
<a href="<%=request.getContextPath() %>/user/admin">管理员</a><br/>
</shiro:hasRole>
3.注解式:
@RequiresAuthentication 验证用户是否登录
@RequiresUser 当前用户已经验证过了或则记住我了
@RequiresGuest 是否是游客身份
@RequiresRoles 判断subject中有aRoleName角色才可以访问方法someMethod 例:@RequiresRoles({“admin”})
@RequiresPermissions 需要拥有权限,例:@RequiresPermissions({“file:read”, “write:aFile.txt”} )
5)个人使用:
a、主要是使用注解@RequiresPermissions和@RequiresRoles,(主要在controller,有些人在controller不生效,说是要在service层。)
b、 注意某些接口会有好几个功能会调用,需求在注解上加上,logical = Logical.OR。默认是and(与)关系。
c、如果俩注解同时使用,是需要同时满足的。(既要拥有角色,也要拥有权限)
d、注意:某些接口需要在配置类中ShiroFilterFactoryBean中设置成anno。比如验证码接口。
e、错误记录:登出错误,报 Request method ‘GET’ not supported。
原因:无论登出是改成post还是get,他都会报get不支持的错误;是因为他请求的是登录接口,而登录接口是post的;这个请求是因为Shiro的过滤器对HttpServletRequest做了处理了,是请求的ShiroHttpServletRequest而不是HttpServletRequest。
解决:shiro对登录的处理也是“/logout”,我们的登出接口也是写的“/logout”。办法有两个:一把我们的接口路径改了,
二把shiro配置中的(“/logout”,”logout”)删了。
遗留问题:为什么调登出会去请求登录接口?对shiro底层不够了解。
参考:参考1,参考2,shiro官网,参考4,参考5,参考6,参考7
四、写代码分析需求的思路转变
- 服务意识,不能只管技术实现,要提升用户体验。
- 先站在用户角度去看,再看技术问题(先看有没有业务价值。不能先从技术角度看)。
- 多考虑问题解决方案,寻找更优,更人性化的。