前言:
如今看官们对“apacheauthz模块”大体比较珍视,小伙伴们都想要学习一些“apacheauthz模块”的相关资讯。那么小编在网摘上网罗了一些对于“apacheauthz模块””的相关文章,希望同学们能喜欢,各位老铁们快快来了解一下吧!通过Shiro实现用户登录验证,授权,对不同用户角色访问资源进行验证,对用户权限访问资源验证,通过迭代加密方式提高用户密码的安全性,本文通过gradle进行构建
引入依赖
compile group: 'org.apache.shiro',name: 'shiro-spring-boot-web-starter',version: '1.4.0'compile group: 'org.apache.shiro',name: 'shiro-ehcache',version: '1.3.2'添加shiro 配置
package com.language.shiro;import com.language.filter.TokenCheckFilter;import org.apache.shiro.authc.credential.CredentialsMatcher;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.cache.CacheManager;import org.apache.shiro.cache.MemoryConstrainedCacheManager;import org.apache.shiro.cache.ehcache.EhCacheManager;import org.apache.shiro.mgt.DefaultSecurityManager;import org.apache.shiro.codec.Base64;import org.apache.shiro.spring.LifecycleBeanPostProcessor;import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.CookieRememberMeManager;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.apache.shiro.session.mgt.SessionManager;import org.apache.shiro.web.servlet.SimpleCookie;import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.DependsOn;import java.util.LinkedHashMap;import java.util.Map;import javax.servlet.Filter;/** * @author ljj * @Date 2019/2/24 19:35 */@Configuration@SuppressWarnings("ALL")public class ShiroConfig { /** * 自定义验证 * @return */ @SuppressWarnings("AlibabaLowerCamelCaseVariableNaming") @Bean ShiroRealm ShiroRealm() { ShiroRealm shiroRealm = new ShiroRealm(); shiroRealm.setCredentialsMatcher(retryLimitCredentialsMatcher()); return shiroRealm; }// /**// *密码加密// * @return// */// @Bean// HashedCredentialsMatcher hashedCredentialsMatcher(){// HashedCredentialsMatcher hashedCredentialsMatcher =new HashedCredentialsMatcher();// //加密方式// hashedCredentialsMatcher.setHashAlgorithmName("SHA1");// //加密次数// hashedCredentialsMatcher.setHashIterations(1024);// return hashedCredentialsMatcher;// } /** * 缓存管理器 * @return cacheManager */ @Bean public EhCacheManager ehCacheManager(){ EhCacheManager cacheManager = new EhCacheManager(); cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml"); return cacheManager; } /** * 限制登录次数(密码加密方式) * @return 匹配器 */ @Bean public CredentialsMatcher retryLimitCredentialsMatcher() { RetryLimitCredentialsMatcher retryLimitCredentialsMatcher = new RetryLimitCredentialsMatcher(ehCacheManager()); retryLimitCredentialsMatcher.setHashAlgorithmName("SHA1"); retryLimitCredentialsMatcher.setHashIterations(1024); // 设置限制 retryLimitCredentialsMatcher.setMaxRetryNum(5); return retryLimitCredentialsMatcher; } /** * cookie对象; * rememberMeCookie()方法是设置Cookie的生成模版,比如cookie的name,cookie的有效时间等等。 * @return */ @Bean public SimpleCookie rememberMeCookie(){ //System.out.println("ShiroConfiguration.rememberMeCookie()"); //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); //<!-- 记住我cookie生效时间30天 ,单位秒;--> simpleCookie.setMaxAge(259200); return simpleCookie; } /** * cookie管理对象; * rememberMeManager()方法是生成rememberMe管理器,而且要将这个rememberMe管理器设置到securityManager中 * @return */ @Bean public CookieRememberMeManager rememberMeManager(){ //System.out.println("ShiroConfiguration.rememberMeManager()"); CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) cookieRememberMeManager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag==")); return cookieRememberMeManager; } @Bean DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager sm = new DefaultWebSecurityManager(); sm.setRealm(ShiroRealm()); sm.setCacheManager(ehCacheManager()); //注入记住我管理器 sm.setRememberMeManager(rememberMeManager()); //注入自定义sessionManager sm.setSessionManager(sessionManager()); return sm; } /** *自定义sessionManager */ @Bean SessionManager sessionManager() { return new MySessionManager(); } @Bean ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); //SecurityUtils.setSecurityManager(securityManager); Map<String, String> filterMap = new LinkedHashMap<>(); //配置不会被拦截的链接,顺序判断 // 配置不会被拦截的链接 顺序判断 filterMap.put("/login", "anon"); filterMap.put("/logout", "anon"); //authc:所有url必须通过认证才能访问,anon:所有url都可以匿名访问 filterMap.put("/**", "authc"); shiroFilter.setFilterChainDefinitionMap(filterMap); //自定义过滤器 Map<String, Filter> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("authc", new TokenCheckFilter()); shiroFilter.setFilters(filterChainDefinitionMap); return shiroFilter; } /** * Shiro生命周期处理器 * @return */ @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * setUsePrefix(true)用于解决一个奇怪的bug。在引入spring aop的情况下。 * 在@Controller注解的类的方法中加入@RequiresRole等shiro注解,会导致该方法无法映射请求,导致返回404。 * 加入这项配置能解决这个bug */ @Bean public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setUsePrefix(true); return defaultAdvisorAutoProxyCreator; } /** * 开启Shiro注解模式,可以在Controller中的方法上添加注解 * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; }}重写 DefaultWebSessionManager实现自定义过滤器
package com.language.shiro;import org.apache.shiro.web.servlet.ShiroHttpServletRequest;import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;import org.apache.shiro.web.util.WebUtils;import org.springframework.util.StringUtils;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.Serializable;/** * 重写 DefaultWebSessionManager * @Author Administrator * @create 2020/3/18 9:01 */public class MySessionManager extends DefaultWebSessionManager { private static final String AUTHORIZATION = "authorization"; private static final String REFERENCED_SESSION_ID_SOURCE = "cookie"; public MySessionManager() { super(); setGlobalSessionTimeout(DEFAULT_GLOBAL_SESSION_TIMEOUT * 1); } @Override protected Serializable getSessionId(ServletRequest request, ServletResponse response) { String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION); //如果请求头中有 Authorization 则其值为sessionId if (!StringUtils.isEmpty(id)) { request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id); request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); return id; } else { //否则按默认规则从cookie取sessionId return super.getSessionId(request, response); } }}重写HashedCredentialsMatcher实现用户(登录次数、过期时间)管理
package com.language.shiro;import com.language.utils.JsonResult;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.ExcessiveAttemptsException;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;import org.apache.shiro.cache.Cache;import org.apache.shiro.cache.ehcache.EhCacheManager;import java.util.concurrent.atomic.AtomicInteger;/** * @Author Administrator * @create 2020/8/20 17:19 */public class RetryLimitCredentialsMatcher extends HashedCredentialsMatcher { private int maxRetryNum = 5; //默认一个小时 private int lockTime = 60; private EhCacheManager shiroEhcacheManager; public void setMaxRetryNum(int maxRetryNum) { this.maxRetryNum = maxRetryNum; } public RetryLimitCredentialsMatcher(EhCacheManager shiroEhcacheManager) { this.shiroEhcacheManager = shiroEhcacheManager; } @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { Cache<String, AtomicInteger> passwordRetryCache = shiroEhcacheManager.getCache("passwordRetryCache"); String username = (String) token.getPrincipal(); //次数+ 1 AtomicInteger retryCount = passwordRetryCache.get(username); if (null == retryCount) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if (retryCount.incrementAndGet() > maxRetryNum) {// throw new ExcessiveAttemptsException(); throw new ExcessiveAttemptsException("用户: " + username + ",认证失败超过"+maxRetryNum+"次,锁定时间:"+lockTime+"分钟"); } boolean matches = super.doCredentialsMatch(token, info); if (matches) { //验证成功清除缓存时间 passwordRetryCache.remove(username); } return matches; }}添加自定义Realm 验证
package com.language.shiro;import com.language.entity.Menu;import com.language.entity.Role;import com.language.entity.User;import com.language.service.UserService;import com.language.utils.JsonResult;import com.language.utils.ServerResponseEnum;import org.apache.shiro.authc.*;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.util.ByteSource;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Lazy;import org.springframework.util.StringUtils;import java.util.ArrayList;import java.util.List;import java.util.Set;/** *实现AuthorizingRealm接口用户用户认证 * @author ljj * @Date 2019/2/24 20:38 */ public class ShiroRealm extends AuthorizingRealm { /** * 用户认证登录 */ @Lazy @Autowired private UserService userService; @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //将token转换成UsernamePasswordToken UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken; // 获取用户名即可 String loginName = upToken.getUsername(); // 获取密码 String password = upToken.getPassword().toString(); upToken.isRememberMe(); if(StringUtils.isEmpty(loginName)){ throw new IncorrectCredentialsException("用户名不能为空"); }else if(StringUtils.isEmpty(password)){ throw new IncorrectCredentialsException("密码不能为空"); } //根据账户名称查询用户信息 User user = userService.getByLoginName(loginName); if(user == null){ throw new UnknownAccountException(); } if(user.getPassword().equals(password)){ throw new IncorrectCredentialsException(); } if(user.getLoginFlag().equals("0")){ throw new LockedAccountException(); } //取出盐并编码 ByteSource salt = ByteSource.Util.bytes(user.getLoginName()); return new SimpleAuthenticationInfo(user, user.getPassword(),salt, getName()); } //用于授权角色权限和对应权限添加 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 需要把角色和权限放入info中 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); // 获取User用户 User user = (User) principals.fromRealm(this.getClass().getName()).iterator().next(); List<String> permissionList = new ArrayList<>(); List<String> roleNameList = new ArrayList<>(); //获取角色信息 List<Role> roleSet = user.getRoles(); if (roleSet != null) { for (Role role : roleSet) { roleNameList.add(role.getName()); List<Menu> menuSet = role.getMenus(); if (menuSet != null) { for (Menu menu : menuSet) { permissionList.add(menu.getName()); } } } } // 权限设定 authorizationInfo.addStringPermissions(permissionList); // 角色设定 authorizationInfo.addRoles(roleNameList); return authorizationInfo; }}controller层实现
package com.language.controller;import com.language.entity.Role;import com.language.entity.User;import com.language.service.UserService;import com.language.utils.JsonResult;import com.language.utils.ServerResponseEnum;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;import org.apache.shiro.subject.Subject;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import java.util.List;/** * 登录 * @author Administrator */@RestController@RequestMapping("")public class LoginController { @Autowired private UserService userService; JsonResult jsonresult =new JsonResult(); @PostMapping("/login") public JsonResult login(@RequestBody User user) { /** * 使用Shrio编写认证操作 */ Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(user.getLoginName(), user.getPassword()); // 登录验证 try { subject.login(token); String sessionId = (String) subject.getSession().getId(); jsonresult.setMsg("登录成功"); jsonresult.setToken(sessionId); return jsonresult; } catch (UnknownAccountException e) { return JsonResult.error(ServerResponseEnum.ACCOUNT_NOT_EXIST); } catch (IncorrectCredentialsException e) { return JsonResult.error(ServerResponseEnum.INCORRECT_CREDENTIALS); } catch (LockedAccountException e) { return JsonResult.error(ServerResponseEnum.ACCOUNT_IS_DISABLED); } catch (ExcessiveAttemptsException e) { return JsonResult.error(1005,e.getMessage()); } catch (Throwable e) { e.printStackTrace(); return JsonResult.error(ServerResponseEnum.ERROR); } } /** * 登出 */ @PostMapping("/logout") public JsonResult logout() { Subject subject = SecurityUtils.getSubject(); subject.logout(); jsonresult.setMsg("安全退出"); return jsonresult; }}dao层实现
package com.language.dao;import com.github.pagehelper.Page;import com.language.common.BaseDao;import com.language.entity.Menu;import com.language.entity.Role;import com.language.entity.User;import org.springframework.stereotype.Repository;import java.util.List;import java.util.Map;/** * 用户Dao接口 * @author Administrator */@Repositorypublic interface UserDao extends BaseDao<User> { /** * 根据登录名称查询用户(用于登录) * @param loginName * @return */public User getByLoginName(String loginName);}Service层实现
package com.language.service;import com.github.pagehelper.Page;import com.language.common.BaseService;import com.language.entity.User;import com.language.utils.JsonResult;import java.util.List;/** * @author Administrator */public interface UserService extends BaseService<User> { /** * 根据登录名称查询用户(用于登录) * @param loginName * @return */ public User getByLoginName(String loginName);}
版权声明:
本站文章均来自互联网搜集,如有侵犯您的权益,请联系我们删除,谢谢。
标签: #apacheauthz模块