如何正确的使用shiro

如何正确的使用shiro,第1张

从来没接触过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.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<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/jsoncharset=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/jsoncharset=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("登录失败!")

}

}

数据库可以自己去设计,这里就不提供了。

参照上面的去整合框架,便可以使用了,这样搭建适合多种框架的整合。

连接池配置文件db.properties是java中采用数据库连接池技术完成应用对数据库的 *** 作的配置文件信息的文件。 具体配置项目如下: drivers=com.microsoft.sqlserver.jdbc.SQLServerDriver 注册驱动,sqlsever,oracle,mysql都行 logfile=d:\\log.tx...


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11695976.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-18
下一篇 2023-05-18

发表评论

登录后才能评论

评论列表(0条)

保存