shiro
1、介绍
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。
2、组成
shiro包含三个核心组件:Subject,SecurityManager,Realms
其中:
subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证,授权。
securityManager:安全管理器,主体进行认证和授权都是通过securityManager进行。
authenticator:认证器,用户身份验证组件,登录控制。
authorizer:授权器,主体进行授权最终通过authorizer进行的。
sessionManager:shiro提供的session的管理的方式
SessionDao:通过SessionDao管理Session数据,使用与存储。
cacheManager:缓存管理器,对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。
relam:域,相当于数据源,通过relam存取认证,授权相关数据。
cryptography:密码管理,提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。
3、登录功能的实现(包含免密登录)
登录流程:
1、应用程序构建了一个终端用户认证信息的AuthenticationToken实例后,调用Subject.login方法
2、Sbuject会委托应用程序设置的securityManager实例调用securityManager.login(token)方法。
3、SecurityManager接受到token(令牌)信息后会委托内置的Authenticator的实例(通常都是ModularRealmAuthenticator类的实例)调用authenticator.authenticate(token).ModularRealmAuthenticator在认证过程中会对设置的一个或多个Realm实例进行适配,它实际上为Shiro提供了一个可拔插的认证机制。
4、如果在应用程序中配置了多个Realm,ModularRealmAuthenticator会根据配置的AuthenticationStrategy(认证策略)来进行多Realm的认证过程。在Realm被调用后,AuthenticationStrategy将对每一个Realm的结果作出响应。
注:如果应用程序中仅配置了一个Realm,Realm将被直接调用而无需再配置认证策略。
5、Realm将调用getAuthenticationInfo(token);getAuthenticationInfo方法就是实际认证处理,我们通过覆盖Realm的doGetAuthenticationInfo方法来编写我们自定义的认证处理。
代码实现:
Controller:
@PostMapping("/login")
public String login(HttpSession session, @RequestBody User user) throws Exception {
String username = user.getUsername();
String companyName = user.getCompanyName();
username = HtmlUtils.htmlEscape(username);
User serviceByUsername = null;
//更具用户名查询用户
serviceByUsername = userService.findByUsername(username);
Subject subject = SecurityUtils.getSubject();
String decodePassword = CryptTool.decodePw(user.getPassword());
//因为业务需求不用,所以这里用用户Id和密码作为UsernamePasswordToken的参数
UsernamePasswordToken token = new UsernamePasswordToken(serviceByUsername.getId(), decodePassword);
token.setRememberMe(true);
try {
subject.login(token);
return jsonSuccess(byUsername, "登录成功");
} catch (AuthenticationException e) {
logger.error("登录失败:"+e.toString());
return jsonFailure("104", "登录失败,请联系管理员");
}
}
subject.login(token)的源码:
shiro目录结构:(其中AuthenticationController用于登录)
自己代码实现:
ShiroConfiguration
package cn.com.rivercloud.secutity.config;
import cn.com.rivercloud.secutity.filter.URLPathMatchingFilter;
import cn.com.rivercloud.secutity.matcher.MyRetryLimitCredentialsMatcher;
import cn.com.rivercloud.secutity.relam.SystemRelam;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
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.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* author shichangle
*
*/