Shiro
Shiro的作用
- Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份。
- Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情。
- Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是Web环境,Shiro有它自己的session。
- Cryptography:加密。保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
- Web Support:Web支持。
- Caching:缓存。
- Concurrency:Shiro支持多线程应用的并发验证,即在一个线程中开启另一个线程,能把权限自动传播过去。
- Testing:提供测试支持。
- Run As:允许一个用户假装为另一个用户(前提是被允许)的身份进行访问。
- Remember Me:记住我。这个是非常常见的功能,即一次登录后,下次就不用登录了,基于cookie。
Shiro的内置过滤器
/*
anon:无需认证,即可访问
authc:必须认证才可访问
user:必须拥有 记住我 才能用
perms:拥有对某个资源的权限才能访问
role:拥有某个角色权限才能访问
*/
过滤级别 | 作用 |
---|---|
anon | 无需认证即可访问 |
authc | 必须认证才可访问 |
user | 必须拥有”记住我”才能用 |
perms | 拥有对某个资源的权限才能访问 |
role | 拥有某个角色权限才能访问 |
shiro相关方法
spring security也有
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
currentUser.isAuthenticated();
currentUser.getPrincipal();
currentUser.hasRole("schwartz");
currentUser.isPermitted("lightsaber:wield");
currentUser.logout();
Shiro配置步骤
1、导入依赖
<!--shiro整合spring-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.0</version>
</dependency>
<!--Shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.6.0</version>
</dependency>
2、自定义一个Realm类,重写授权与认证方法
/**
* 自定义的Realm
*/
public class UserRealm extends AuthorizingRealm {
@Resource
AdminMapper adminMapper;
/**
* 授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了=>授权doGetAuthorizationInfo");
return null;
}
/**
* 认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了=>认证doGetAuthenticationInfo");
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken; //取得账户密码令牌
Admin admin = adminMapper.queryAdmin(userToken.getUsername());
if (admin == null) {
return null; //抛出异常UnknownAccountException
}
//密码认证
return new SimpleAuthenticationInfo("", admin.getPassword(), "");
}
}
3、写一个Shiro的配置类
@Configuration
public class ShiroConfig {
@Bean(value = "userRealm")
public UserRealm getUserRealm() {
return new UserRealm();
}
@Bean(value = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm); //装配自定义的userRealm
return securityManager;
}
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(securityManager); //安全管理器
//添加shiro的内置过滤器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/blog.html", "authc");
filterChainDefinitionMap.put("/list.html", "authc");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
bean.setLoginUrl("/admin/toLogin"); //被拦截后跳转到登录页面
return bean;
}
}
4、controller层
@RequestMapping("/login")
public String login(@RequestParam("name") String name, @RequestParam("password") String password,
Model model, HttpSession session) {
//获取用户名和密码
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(name, password);
try {
subject.login(token); //判断用户名和密码是否正确,不正确则抛出异常
Admin admin = adminMapper.queryAdmin(name);
session.setAttribute("login_admin", admin);
return "blog";
}catch (UnknownAccountException e) { //用户不存在
model.addAttribute("msg", "用户名错误");
return "login";
}catch (IncorrectCredentialsException e) { //密码错误
model.addAttribute("msg", "密码错误");
return "login";
}
}