shiro-web认证流程
一、认证流程
- 访问Controller接口,获取Subject对象,实现UsernamePasswordToken,调用subject对象login方法,进入AuthenticationRealm对象中的getAuthenticationInfo方法中。
- 先判断缓存中是否存在认证信息,若没有跳转到自定义Realm【注册到SubjectManager中[并且在Realm中配置加密策略]】的doGetAuthenticationInfo中,通过token获取用户名调用数据库获取用户信息,封装为SimpleAuthenticationInfo对象返回即可。
二、注册自定义Realm
作用 :实现认证和授权
继承AuthorizingRealm类重载 protected AuthenticationInfo doGtAuthenticationInfo(AuthenticationToken token)
三、Code
1、配置自定义Realm
public class MyShiroRealm extends AuthorizingRealm {
@Resource
private AdminUserService adminUserService;
@Resource
private PermissionService permissionService;
/**
* 授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
Integer id = (Integer) principalCollection.getPrimaryPrincipal();
List<Permission> permissionList = permissionService.loadUserPermission(id);
// 权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
permissionList.forEach(p->info.addStringPermission(p.getPerurl()));
return info;
}
/**
* 认证
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取用户的输入的账号.
String username = (String)token.getPrincipal();
AdminUser user = adminUserService.findByUserName(username);
if(user==null) throw new UnknownAccountException();
if (0==user.getEnable()) {
throw new LockedAccountException(); // 帐号锁定
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getId(), //用户
user.getPassword(), //密码
ByteSource.Util.bytes(username),
getName() //realm name
);
// 把用户信息放在session里
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("AdminSession", user);
session.setAttribute("AdminSessionId", user.getId());
return authenticationInfo;
}
}
2、配置Realm到SecurityManager
@Configuration
public class ShiroConfig {
@Autowired
private PermissionService permissionService;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.password}")
private String password;
/**
* 凭证匹配器
*
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");
hashedCredentialsMatcher.setHashIterations(2);//散列的次数,相当于 md5(md5(""));
return hashedCredentialsMatcher;
}
//配置自定义Realm
@Bean
public Realm getMyShiroRealm() {
MyShiroRealm mShiroRealm = new MyShiroRealm();
//配置加密凭证
mShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return mShiroRealm;
}
//配置SecurityManager
@Bean
public SecurityManager securityManager() {
//类似于DispatcherServlet
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置realm.【类似于DataSource】
securityManager.setRealm(getMyShiroRealm());
return securityManager;
}
/**
* 处理拦截资源文件问题。
*
* @param securityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.html"页面
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/initPage");
//未授权界面
shiroFilterFactoryBean.setUnauthorizedUrl("/forbidden");
//拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/favicon.png", "anon");//解决弹出favicon.ico下载
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/font-awesome/**", "anon");
filterChainDefinitionMap.put("/", "anon");
//自定义加载权限资源关系
List<Permission> list = permissionService.findAll();
for (Permission p : list) {
if (!p.getPerurl().isEmpty()) {
String permission = "perms[" + p.getPerurl() + "]";
filterChainDefinitionMap.put(p.getPerurl(), permission);
}
}
//过滤链定义,从上向下顺序执行,一般将 /**放在最为下边
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
}