前台使用shiro框架后如何直接访问首页
从来没接触过shiro Java安全框架,突然有一天需要要用用户登陆验证和用户角色权限的任务,而且是针对shiro 进行整合,开始收到任务,心都有点凉凉的。经过一轮的搜索,感觉没多大的收获。很多用户的角色都是写在xml配置文件中。觉得太不人性化了,想换个用户角色还得改xml?我觉得这么强大的框架应该不可能这么狗血的存在。然后认真的看文档,发现真的是可以直接读取数据库的。我把我搭建的流程发布在此。有问题的可以交流交流。我写的也并不是正确的,只能参考参考。
1.web.xml的配置
org.apache.shiro.web.env.EnvironmentLoaderListener
shiroFilter
org.apache.shiro.web.servlet.ShiroFilter
shiroFilter
/*
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.dao.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 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 result = new Result(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 result = new Result(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("登录失败!");
}
}
数据库可以自己去设计,这里就不提供了。
参照上面的去整合框架,便可以使用了,这样搭建适合多种框架的整合。
一般的网站都分前台和后台,并且分别有两个登陆地址对应不同的数据库表,那么如果通过apache shiro分别对前台和后台进行权限控制呢?求解
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/" />
<!-- <property name="loginUrl" value="/userIndex/scsIndex" /> -->
<property name="successUrl" value="/index" />
<property name="unauthorizedUrl" value="/GoLogin" />
<property name="filterChainDefinitions">
<value>
/static/js/myjs/** = authc
/static/** = anon
/userIndex/** = anon
/WEB-INF/jsp/userIndex/** = anon
/** = authc
</value>
</property>
</bean>
我是直接把loginUrl的property标签的VALUE指向首页的路径,虽然可以实现这个效果,但还不是很理想,还在学习中。
/ = anon 。
使用shiro框架的时候是不是必须把动态代理设置成cglib
推荐一套完整的Shiro Demo,免费的。Shiro Demo:http:\/\/www.sojson.com\/shiroDemo已经部署到线上,地址是http:\/\/shiro.itboy.net管理员帐号:admin,密码:sojson.com 如果密码错误,请用sojson。PS:你可以注册自己的帐号,然后用管理员赋权限给你自己的帐号,但是,每20分钟会把数据初始化一次。
若依 权限框架 Shiro
当然两种访问方式可以单独使用,也可以混合使用。比如对于比较简单的权限控制,你可以仅仅只使用基于角色的访问控制,仅仅引入角色表,不需要权限表都可以。混合使用是指,你可以同时要求用户具有某角色并且具有某些权限,才能访问某资源。所以shiro的权限控制时极其灵活的(当然也可以不引入角色表,仅仅引入权限表...
shiro和jwt区别
不是一回事 shiro是一套权限管理框架,包括认证、授权等,在使用时直接写相应的接口就可以了,已经把底层处理都写好了 而jwt只是一种生成token的机制,所有权限处理逻辑还需要自己写
shiro权限框架怎么样
用来保护RESTful资源不错:HTTP Authentication and Security with Apache Shiro 据说1.2版本和OAuth能够整合,但是没有看到容易整合的资料,现在OAuth应用非常广泛多,也许两者也有重叠部分。有时Java内部自己的开源会把开发者带到一个支路,而支持众多语言的开源项目一般比较主流强壮,特别是系统接口部分的开源...
请问java开发一个不是特别大的系统时,有必要用security等认证授权...
一般来说使用security作为权限框架更精细,但是相比于shiro还是略显繁琐了,shiro更小巧简便,小型项目当中,没有必要使用security,但是直接使用mvc拦截器这种过时的东西又不是很安全,所以推荐的就是 shiro;如果还想更简单更方便,推荐使用sa-token;可以说是配置最少,如同它的介绍一样。一个轻量级 Java ...
shiro中的anon,authc啥意思
2. authc:当某个资源或操作需要用户进行身份验证才能访问时,就会使用authc过滤器。这意味着用户必须先登录并提供有效的凭据,才能访问被authc保护的资源或执行相应的操作。这是一种常见的安全策略,确保只有经过身份验证的用户才能访问敏感数据或执行关键操作。Shiro框架通过这两个过滤器名称简化了权限和身份...
浅谈Apache Shiro CVE-2023-22602
复现该漏洞的过程涉及配置ShiroFilter以拦截特定路径,同时利用PathPattern的特性。在Shiro 1.11.0及之前版本中,尝试使用\/admin\/{*path}这样的路径可能导致绕过安全控制。而在1.11.0之后,由于切换至AntPathMatcher,不支持这种动态路径匹配,导致访问错误或安全漏洞被封堵。修复建议是升级Shiro到1.11.0及...
shiro框架 RequiresPermissions注解怎么动态配置
用alt+\/后会出现提示 value是一个数组的格式,数组可以类似这样写 @RequiresPermissions(value = { "权限1","权限2" })
springMvc+shiro做权限管理,页面上的静态资源,样式图片等没有出现,用...
\/css\/** = anon 配置完成后,未登录就可以在浏览器中直接访问css下的资源,新项目用的shiro,简单而又实用的权限框架。在shiroFilter 和 mvc:resources中都需要配置,如:shiroFilter中:<property name="filterChainDefinitions"> <value> \/css\/** = anon \/js\/** = anon \/img\/** = anon <\/...
oauth2 和shiro的区别
oauth2 和shiro的区别为:性质不同、语言不同、用途不同。一、性质不同 1、oauth2 :是OAuth协议的延续版本,但不向前兼容OAuth 2.0(即完全废止了OAuth1.0)。2、shiro:是一个强大且易用的Java安全框架。二、语言不同 1、oauth2 :PHP、JavaScript,Java 2、shiro:Java 三、用途不同 1、oauth...
枞看贝复: --> /static/js/myjs/** = authc /static/** = anon /userIndex/** = anon /WEB-INF/jsp/userIndex/** = anon /** = authc 我是直接把loginUrl的property标签的VALUE指向首页的路径,虽然可以实现这个效果,但还不是很理想,还在学习中.
礼泉县13883631530: shiro前后台分开登录怎么实现 - ?
枞看贝复: 您好,很高兴为您解答:1、力推 Filter 过滤器,2、后台判断根据权限跳转页面登陆成功后获取 Subject 对象.然后通过 Subject 对象来判断当前用户的角色/权限,之后执行不同的跳转(直接在LoginAction中做).如果我的回答没帮助到您,请继续追问.
礼泉县13883631530: springMvc+shiro跳过登陆 - ?
枞看贝复: springmvc集成shiro登录失败处理 一般的登录流程会有:用户名不存在,密码错误,验证码错误等..在集成shiro后,应用程序的外部访问权限以及访问控制交给了shiro来管理.shiro提供了两个主要功能:认证(Authentication)和授权(...
礼泉县13883631530: 怎么直接访问jsp页面 - ?
枞看贝复: 1、用submit按钮跳转到指定页面,action = ""xxxx.jsp" 2、window.location.href="xxxx.jsp" 3、window.open("xxxx.jsp") 4、 5、
礼泉县13883631530: 如何访站,前台和后台??
枞看贝复: 前台一般是网站开始,直接就可以访问,至于后台的话,要看站长在FTP里面存放后台数据的名字是什么 ,一般是admin那你可以直接在他域名后加上ADMIN访问.如果他把名字改了,那你要确定他现在的文件名.不过后台一般都要加密的 希望对你有用
礼泉县13883631530: SpringMVC shiro 项目 jeesite框架,启动后可以访问,等待约30分钟或更久之后,第一次访问会卡住. - ?
枞看贝复: 应该是session超时导致的,shiro的默认设置会话的全局过期时间30分钟:
礼泉县13883631530: ssh框架 hibernate 一对一关联,怎么从前台获取到两个表的数据,还有在前台显示两个表的数据. - ?
枞看贝复: 显示的时候,如果用的jstl 直接${object.value.value} 直接点过去就行了 其它前台的显示也差不多,都是直接对象.变量.变量
礼泉县13883631530: 后台如何访问前台界面中的HTML控件 - ?
枞看贝复: 方法1在前台div 加一个runat="server" 在后台就能看到了.方法2在后台注册js代码,js代码里面也可以获得这个div 然后就可以了 希望回答对你有帮助,如果有疑问,请继续追问
礼泉县13883631530: spring boot 集成shiro,设置好setLoginUrl后,报404 - ?
枞看贝复: 正常情况是不会出现这样的,shiro对于静态资源的处理,不用特殊配置,只需要在shiroFilter过滤器filterChainDefinitions项中增加一个静态资源处理规则就可以,例如允许/css/开头的资源匿名访问,只需要这样一句配置就足矣, /css/** = anon 配
礼泉县13883631530: C#后台调用前台js的方法? - ?
枞看贝复: 在网上找了找,发现有三种方法可以访问到前台代码: 第一种,OnClientClick (vs2003不支持这个方法)<br><asp:Button ID="Button1" <br>runat="server" Text="Button" <br>nClientClick="client_click()" <br>nClick="Button1_Click" /...