一、权限框架介绍
1. 权限治理
实质:用户身份认证+受权
流程:用户首先通过身份认证,通过后即可拜访该资源
1.1 用户身份认证
1.2 受权流程
2. 权限框架
Shiro和Spring Security比拟
(1)Shiro比Spring更容易应用,实现和了解
(2)Spring Security有更好的社区反对
(3)Apache Shiro在Spring Security解决密码学方面有一个额定的模块
(4)Spring-security 对spring 联合较好,如果我的项目用的springmvc ,应用起来很不便。然而如果我的项目中没有用到spring,那就不要思考它了。
(5)Shiro 功能强大、且 简略、灵便。是Apache 下的我的项目比拟牢靠,且不跟任何的框架或者容器绑定,能够独立运行
二、Shiro根底介绍
1. Shiro三个外围组件
1.1 Subject(以后操作用户)
不仅仅指人,也能够是第三方过程、后盾帐户(Daemon Account)或其余相似事物。Subject代表了以后用户的平安操作,SecurityManager则治理所有用户的平安操作。
1.2 SecurityManager(保护核心)
Shiro框架的外围,典型的Facade模式,用来协调外部组件实例,并提供平安治理的各种服务。
1.3 Realm(数据中心)
对用户认证(登录)和受权(访问控制)时,Shiro会从配置的Realm中查找用户及其权限信息。
当配置Shiro时,至多指定一个Realm,用于认证和(或)受权。配置多个Realm是能够的,然而至多须要一个。
Shiro内置了能够连贯大量平安数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、相似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需要,你还能够插入代表自定义数据源的本人的Realm实现。
2. Shiro相干类介绍
(1)Authentication 认证 —- 用户登录
(2)Authorization 受权 — 用户具备哪些权限
(3)Cryptography 平安数据加密
(4)Session Management 会话治理
(5)Web Integration web系统集成
(6)Interations 集成其它利用,spring、缓存框架
3. Shiro 特点
(1)易于了解的 Java Security API;
(2)简略的身份认证(登录),反对多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory 等);
(3)对角色的简略的签权(访问控制),反对细粒度的签权;
(4)反对一级缓存,以晋升应用程序的性能;
(5)内置的基于 POJO 企业会话治理,实用于 Web 以及非 Web 的环境;
(6)异构客户端会话拜访;
(7)非常简单的加密 API;
(8)不跟任何的框架或者容器捆绑,能够独立运行
三、Spring Boot整合Shiro代码实战
3.1 pom.xml中增加依赖
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
3.2 编写测试Controller类
@RequiresPermissions("user:list")
@RequiresRoles("admin")
@ResponseBody
@RequestMapping("/hello")
public String hello(){
System.out.println(person);
return "hello world";
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
@ResponseBody
public String defaultLogin() {
return "首页";
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public String login(@RequestParam("username") String username, @RequestParam("password") String password) {
// 从SecurityUtils里边创立一个 subject Subject subject = SecurityUtils.getSubject();
// 在认证提交前筹备 token(令牌)
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
// 执行认证登陆
try {
subject.login(token);
} catch (UnknownAccountException uae) {
return "未知账户";
} catch (IncorrectCredentialsException ice) {
return "明码不正确";
} catch (LockedAccountException lae) {
return "账户已锁定";
} catch (ExcessiveAttemptsException eae) {
return "用户名或明码谬误次数过多";
} catch (AuthenticationException ae) {
return "用户名或明码不正确!";
}
if (subject.isAuthenticated()) {
return "登录胜利";
} else {
token.clear();
return "登录失败";
}
}
3.3 配置类
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setSecurityManager(securityManager);
//增加Shiro内置过滤器
/**
* Shiro内置过滤器,能够实现权限相干的拦截器
* 罕用的过滤器:
* anon: 无需认证(登录)能够拜访
* authc: 必须认证才能够拜访
* user: 如果应用rememberMe的性能能够间接拜访
* perms: 该资源必须失去资源权限才能够拜访
* role: 该资源必须失去角色权限才能够拜访
*/
shiroFilterFactoryBean.setLoginUrl("/login");//登录页
shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// <!-- authc:所有url都必须认证通过才能够拜访; anon:所有url都都能够匿名拜访-->
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/", "anon");
filterChainDefinitionMap.put("/front/**", "anon");
filterChainDefinitionMap.put("/api/**", "anon");
filterChainDefinitionMap.put("/admin/**", "authc");
filterChainDefinitionMap.put("/user/**", "authc");
filterChainDefinitionMap.put("/hello/**","perms[user:add]");
//次要这行代码必须放在所有权限设置的最初,不然会导致所有 url 都被拦挡 残余的都须要认证
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
defaultSecurityManager.setRealm(customRealm());
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
defaultSecurityManager.setSubjectDAO(subjectDAO);
return defaultSecurityManager;
}
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
@Bean
public CustomRealm customRealm() {
CustomRealm customRealm = new CustomRealm();
return customRealm;
}
3.4 Realm
/**
* 权限认证,即登录过后,每个身份不肯定,对应的所能看的页面也不一样。
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
User user = null;
String username = "";
if (Objects.nonNull(principalCollection)){
user = (User)principalCollection.getPrimaryPrincipal();
}
username = (String) SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//用户角色
Set<String> roleSets = new HashSet<>();
roleSets.add("admin");
roleSets.add("test");
info.setRoles(roleSets);
//角色对应的权限
Set<String> permissionSet = new HashSet<>();
permissionSet.add("user:show");
permissionSet.add("user:admin");
info.addStringPermissions(permissionSet);
return info;
}
/**
* 身份认证。即登录通过账号和明码验证登陆人的身份信息。
* @param authenticationToken
* @return
* @throws AuthenticationException
*/@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("-------身份认证办法--------");
//authenticationToken.getCredentials()----token?如何来?
String token = (String) authenticationToken.getCredentials();
if (StringUtils.isEmpty(token)){
HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
Map<String, String[]> parameterMap = request.getParameterMap();
Set<Map.Entry<String, String[]>> entrys = parameterMap.entrySet();
for (Map.Entry<String, String[]> entry:entrys) {
System.out.println(entry.getKey()+"============"+entry.getValue());
}
throw new AuthenticationException("token为空");
}
User user = this.checkAuthenticationToken(token);
//String userName = (String) authenticationToken.getPrincipal();
//String userPwd = new String((char[]) authenticationToken.getCredentials()); return new SimpleAuthenticationInfo(user, token,getName());
}
发表回复