问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何正确的使用shiro

发布网友 发布时间:2022-04-21 17:59

我来回答

1个回答

热心网友 时间:2022-04-08 12:25

从来没接触过shiro Java安全框架,突然有一天需要要用用户登陆验证和用户角色权限的任务,而且是针对shiro 进行整合,开始收到任务,心都有点凉凉的。经过一轮的搜索,感觉没多大的收获。很多用户的角色都是写在xml配置文件中。觉得太不人性化了,想换个用户角色还得改xml?我觉得这么强大的框架应该不可能这么狗血的存在。然后认真的看文档,发现真的是可以直接读取数据库的。我把我搭建的流程发布在此。有问题的可以交流交流。我写的也并不是正确的,只能参考参考。
1.web.xml的配置
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.shiro.ini配置
[main]
[filters]
#自定义realm
shiroAuthorizingRealm = com.frame.security.ShiroAuthorizingRealm
securityManager.realm = $shiroAuthorizingRealm
# 声明一个自定义的用户校验*
customFormAuthenticationFilter = com.frame.security.CustomFormAuthenticationFilter
# 声明一个自定义的用户角色权限*
customPermissionsAuthorizationFilter = com.frame.security.CustomPermissionsAuthorizationFilter
#cache
shiroCacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
shiroCacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $shiroCacheManager
#session
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionManager.sessionDAO = $sessionDAO
securityManager.sessionManager = $sessionManager
securityManager.sessionManager.globalSessionTimeout = 1800000
securityManager = org.apache.shiro.web.mgt.DefaultWebSecurityManager
[urls]
/admin/user/login = anon
/admin/user/logout = anon
/admin/user/registered = anon
/admin/** = customFormAuthenticationFilter,customPermissionsAuthorizationFilter
从shiro.ini配置中可以看出,需要三个文件,分别为ShiroAuthorizingRealm.java(realm文件),CustomFormAuthenticationFilter.java(自定义用户登陆验证文件),CustomPermissionsAuthorizationFilter(自定义用户角色权限文件);
在urls配置中可以看出不需要拦截的url后面加上anon便可,但有先后顺序。
缓存是使用ehcache
3.ehcache.xml配置
<cache name="defaultCache" maxElementsInMemory="500"
maxElementsOnDisk="10000000" eternal="true" overflowToDisk="true"
diskSpoolBufferSizeMB="50" />
<cache name="shiro-activeSessionCache" maxElementsInMemory="500"
maxElementsOnDisk="10000000" eternal="true" overflowToDisk="true"
diskSpoolBufferSizeMB="50" />
<cache name="jdbcRealm.authorizationCache" maxElementsInMemory="500"
maxElementsOnDisk="10000000" eternal="true" overflowToDisk="true"
diskSpoolBufferSizeMB="50" />
<cache name="authorization" maxElementsInMemory="500"
timeToLiveSeconds="3600" eternal="false" overflowToDisk="false" />
4.ShiroAuthorizingRealm.java
public class ShiroAuthorizingRealm extends AuthorizingRealm {
private AuthorityService authorityService = FrameContext.getBean(AuthorityService.class);
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("=======doGetAuthenticationInfo=======");
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
String username = userToken.getUsername();
String password = String.valueOf(userToken.getPassword());
User user = User..findFirst("select * from m_user where account = ?", username);
if (user != null) {//下面可以做一些登陆的操作,密码错误,用户状态等等
if(MD5Encoder.validPassword(password, user.getPassword())==false){
throw new UnknownAccountException();
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
return info;
} else {
return null;
}
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("=======doGetAuthorizationInfo=======");
User user = (User) principals.getPrimaryPrincipal();
if(user!=null){//从数据库中读取用户的角色权限,
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
List<String> perms = authorityService.getUrlByUser(user);
if(perms!=null&&perms.size()>0){//调用addStringPermissions方法把用户的权限信息添加到info中,可以addRoles方法把用户的角色添加到了info中
info.addStringPermissions(perms);
}
return info;
}
return null;
}
}
5.CustomFormAuthenticationFilter.java
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
private final static Logger log = Logger.getLogger(CustomFormAuthenticationFilter.class);
private static final String contentType = "application/json; charset=UTF-8";
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpRequest = WebUtils.toHttp(request);
HttpServletResponse httpResponse = WebUtils.toHttp(response);
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
if (log.isTraceEnabled()) {
log.trace("Login submission detected. Attempting to execute login.");
}
return executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
return true;
}
} else {
Result<Object> result = new Result<Object>(false, "401", "没有授权,请先登录", null);
renderJson(httpResponse, result);
return false;
}
}
private void renderJson(HttpServletResponse response, Object object) {
String jsonText = JsonKit.toJson(object);
PrintWriter writer = null;
try {
response.setHeader("Pragma", "no-cache"); // HTTP/1.0 caches might not implement Cache-Control and might only implement Pragma: no-cache
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType(contentType);
writer = response.getWriter();
writer.write(jsonText);
writer.flush();
} catch (IOException e) {
throw new RenderException(e);
}
finally {
if (writer != null) {
writer.close();
}
}
}
}
6.CustomPermissionsAuthorizationFilter.java
public class CustomPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {
private static final String contentType = "application/json; charset=UTF-8";
private AuthorityService authorityService = McmsContext.getBean(AuthorityService.class);

@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
if(getMappedValue(request)!=null){
return super.isAccessAllowed(request, response, getMappedValue(request));
}
return false;

}

@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
// TODO Auto-generated method stub

HttpServletRequest httpRequest = WebUtils.toHttp(request);
HttpServletResponse httpResponse = WebUtils.toHttp(response);
String path = httpRequest.getServletPath();
Subject subject = getSubject(request, response);
if (subject.isPermitted(path)) {
return true;
} else {
Result<Object> result = new Result<Object>(false, "401", "抱歉,您没有该权限!", null);
renderJson(httpResponse, result);
return false;
}

}

/**
* 得到mappedValue,相当于perms[user:add]中的“user:add”
* @param path
* @return
*/
public String[] getMappedValue(ServletRequest request) {
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getServletPath();
String code = getCodesByPath(path);
if(null == code) {
return null;
}
return new String[]{code};
}
/**
* 根据访问路径获取权限代码
* @param path
* @return
*/
public String getCodesByPath(String path) {
User user = (User) SecurityUtils.getSubject().getPrincipal();
String pers = authorityService.getUrlByUserPath(path,user);
return Optional.ofNullable(pers).orElse(null);
}

private void renderJson(HttpServletResponse response, Object object) {
String jsonText = JsonKit.toJson(object);
PrintWriter writer = null;
try {
response.setHeader("Pragma", "no-cache"); // HTTP/1.0 caches might not implement Cache-Control and might only implement Pragma: no-cache
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setContentType(contentType);
writer = response.getWriter();
writer.write(jsonText);
writer.flush();
} catch (IOException e) {
throw new RenderException(e);
}
finally {
if (writer != null) {
writer.close();
}
}
}
}
7.用户登陆入口
public void login() {
String account = getPara("account");
String password = getPara("password");
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken tokens = new UsernamePasswordToken(account, password);
tokens.setRememberMe(false);
try {
subject.login(tokens);
User user = (User) subject.getPrincipal();
loginSuccess(user);
UserVo userVo = convertToUserVO(user);
renderSucessResult(userVo);
} catch (UnknownAccountException ue) {
tokens.clear();
renderFailedResult("登录失败!无效的账号或密码!");
} catch (IncorrectCredentialsException ie) {
tokens.clear();
renderFailedResult("用户已注销!");
} catch(LockedAccountException le){
tokens.clear();
renderFailedResult("账号被锁定!");
} catch (RuntimeException re) {
re.printStackTrace();
tokens.clear();
renderFailedResult("登录失败!");
}

}
数据库可以自己去设计,这里就不提供了。
参照上面的去整合框架,便可以使用了,这样搭建适合多种框架的整合。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
女生多大后可以不在长身高? 如何不用软件把手机投屏到电脑上手机屏幕怎样投放到电脑上 战时拒绝、故意延误军事订货罪既遂的处罚? 战时故意延误军事订货罪处罚标准 名师1+1导读方案:汤姆·索亚历险记目录 三星sm-g7200打开微信慢,无法正常收看,网速不慢。 笔记本电脑如何调亮屏幕亮度 大伙说说洗衣机要不要带烘干好 热烘干洗衣机怎么样 ef英语哪个好 java中的空指针异常怎么解决 java中做字符串非空判断,为什么要同时判断字符串... VB中的关键字与函数 请问VB中的‘保留字’和C语言的‘关键字’是一样的吗?... 如何更好地使用Java 8的Optional 关于图形的解像度[JAVA]. 关于图形的解像度[JAVA]. 新配电脑蓝屏,代码0x00000124,请教各位大神怎么... 新配电脑蓝屏,代码0x00000124,请教各位大神怎么... 按照从小到大图顺序排列下面各数.80800、800800、... 按照从小到大图顺序排列下面各数.80800、800800、... 爱江山更爱美人QQ2013800800、578000555是骗子,骗... 爱江山更爱美人QQ2013800800、578000555是骗子,骗... 相机拍出来的照片改像素800800为何会变形呢?? 相机拍出来的照片改像素800800为何会变形呢?? ps图片怎么裁剪800800像素 和桂源铺差不多的品牌的有哪些? 桂源铺 高巷路店怎么样 江湖风云月似钩的对联有? 江湖风云录全攻略流程是什么? scala option 怎么取值 如何更好的使用 Java 如何使用VB制作这样的程序 VB修改注册表问题 C语言编程1 switch怎么改账号密码? switch账号怎么改年龄 所有的鳖都是龟,但所有的鳖不是乌龟也不是海龟是吗? switch账号改密码 田野里的野生鳖龟越来越少,是都被捕捞了吗? switch修改存档 鳖乌龟王八甲鱼的区别 任天堂NS怎么更改时间 老鳖跟乌龟有啥区别? 王八和乌龟的区别是什么? 乌龟和鳖有什么区别? switch账号怎么改邮箱 鱼虾鳖龟螃蟹属于什么类? switch怎么改密码 发现一个池塘里有甲鱼,怎么才能抓到它呢?