该demo整合Shiro的相关配置参考开涛的博客
数据库表格相关设计
表格设计得比较简单,导航栏直接由角色表auth_role的角色描述vRoleDesc(父结点)和角色相关权限中的权限描述(标记为导航结点)vPermissionDesc(展开子项)组成。
Shiro相关设置
密码输入错误次数限制
//密码重试5次次数限制
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher{
private Cache passwordRetryCache;
public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager){
passwordRetryCache=cacheManager.getCache("passwordRetryCache");
}
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
String username=(String)token.getPrincipal();
AtomicInteger retryCount=passwordRetryCache.get(username);
if(retryCount==null){
retryCount=new AtomicInteger(0);
passwordRetryCache.put(username, retryCount);
}
if(retryCount.incrementAndGet()>5){
throw new ExcessiveAttemptsException();
}
boolean matches= super.doCredentialsMatch(token, info);//匹配密码
if(matches){
passwordRetryCache.remove(username);
}
return matches;
}
}
相关配置:
使用缓存实现为ehcache,相关配置如下:
xsi:noNamespaceSchemaLocation="ehcache.xsd">
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
扩展AuthorizingRealm:用于从数据库抓取密码等相关验证信息和相关权限信息
public class UserRealm extends AuthorizingRealm{
@Autowired
private UserService userService;
//获取相关授权信息
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName=(String)principals.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
authorizationInfo.setRoles(userService.findPermissionsByUserName(userName));//获取角色信息
authorizationInfo.setStringPermissions(userService.findPermissionsByUserName(userName));//获取权限信息
return authorizationInfo;
}
//获取身份验证信息
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName=(String)token.getPrincipal();
User user=userService.getUserByUserName(userName);//获取身份信息(密码和密码盐)
if(user==null){
throw new UnknownAccountException();
}
SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
user.getUserName(),
user.getPassword(),
ByteSource.Util.bytes(user.getUserName()+user.getPasswordSalt()),
getName());
return authenticationInfo;
}
}
登录相关
扩展FormAuthenticationFilter:用于登录后获取用户导航栏,并将其存入session范围
public class WithNavibarFormAuthenticationFilter extends FormAuthenticationFilter {
@Autowired
private UserService userService;
@Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
ServletResponse response) throws Exception {
HttpServletRequest httpReq=(HttpServletRequest)request;
String userName=(String)SecurityUtils.getSubject().getPrincipal();
List navigationBar=userService.getNavigationBar(userName);
httpReq.getSession().setAttribute("navibar", navigationBar);
return super.onLoginSuccess(token, subject, request, response);
}
}
登录Controller实现(用户密码不匹配情况下执行)
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
//...
@RequestMapping("/login")
public ModelAndView login(HttpServletRequest req){
String error=null;
String exceptionClassName = (String)req.getAttribute("shiroLoginFailure");
if(UnknownAccountException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if(exceptionClassName != null) {
error = "其他错误:" + exceptionClassName;
}
ModelAndView mav=new ModelAndView("login");
mav.addObject("error", error);
return mav;
}
//...
}
登录表单代码:注意提交action=”“,以及输入控件name值须与form表单过滤器中的设置对应
请登录
用户名
密码
记住我
${error}
登录
最后通过Spring注解,控制访问
@RequiresPermissions("user:list")
@RequestMapping("/list")
public ModelAndView showUserList(){
//
}
完整shiro配置如下:
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">