Shiro免密登录
Posted mry6
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shiro免密登录相关的知识,希望对你有一定的参考价值。
Shiro免密登录
代码构成
1.创建枚举类LoginType
/**
* 登录类型
*/
public enum LoginType {
PASSWORD("password"), // 密码登录
NOPASSWD("nopassword"); // 免密登录
private String code;// 状态值
private LoginType(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
2.自定义token类CustomeToken,继承UsernamePasswordToken类,通过构造方法区分密码登录和免密登录。
/**
* 自定义token 继承UsernamePasswordToken
*
*/
public class CustomeToken extends UsernamePasswordToken {
private static final long serialVersionUID = -2564928913725078138L;
private LoginType type;
public CustomeToken() {
super();
}
public CustomeToken(String username, String password, LoginType type, boolean rememberMe, String host) {
super(username, password, rememberMe, host);
this.type = type;
}
/**
* 免密登录
*/
public CustomeToken(String username) {
super(username, "", false, null);
this.type = LoginType.NOPASSWD;
}
/**
* 账号密码登录
*/
public CustomeToken(String username, String password) {
super(username, password, false, null);
this.type = LoginType.PASSWORD;
}
public LoginType getType() {
return type;
}
public void setType(LoginType type) {
this.type = type;
}
}
3.修改自定义的CustomeRealm,这个类继承了AuthorizingRealm类。
@Component
public class CustomeRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String loginName = (String)principals.getPrimaryPrincipal();
System.out.println("调用授权验证:" + loginName);
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//用户权限列表
//TODO此处的用户权限列表可以根据自己实际业务进行数据库数据查询
Set<String> permsSet = new HashSet<>();
authorizationInfo.setStringPermissions(permsSet);
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
//从传过来的token获取到用户名
String principal = (String)token.getPrincipal();
System.out.println("调用认证 ===> " + principal);
ByteSource salt = ByteSource.Util.bytes(principal);
String newPs = new SimpleHash("MD5","123",salt,1024).toHex();
//return new SimpleAuthenticationInfo(principal,newPs,salt,this.getName());
return new SimpleAuthenticationInfo(principal, null, this.getName());
}
}
4.自定义CostomeCredentialsMatch类继承HashedCredentialsMatcher类,覆写其中的doCredentialsMatch方法,将token强转为自定义token,若loginType是免密登录,则直接返回true,否则执行父类比对。
public class CustomCredentialsMatch extends HashedCredentialsMatcher {
@Override
public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {
CustomToken tk = (CustomToken) authcToken;
if(tk.getType().equals(LoginType.NOPASSWD)){
return true;
}
boolean matches = super.doCredentialsMatch(authcToken, info);
return matches;
}
}
5.ShiroConfig文件
@Configuration
public class ShiroConfig{
//1.创建shiroFilter,负责拦截所有请求
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//给filter设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
Map<String,String> map = new HashMap<String,String>();
map.put("/initindex","anon");
map.put("/sys/**","anon");
map.put("/app/**","anon");
//authc 请求这个资源需要认证
map.put("/**","authc");
//默认认证界面路径 --- 当认证不通过时跳转
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//2.创建安全管理器
@Bean("securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("getRealm") Realm realm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//给安全管理器设置自定义Realm
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
}
//3.创建自定义Realm
@Bean
public Realm getRealm(CustomCredentialsMatch matcher){
CustomerRealm customerRealm = new CustomerRealm();
customerRealm.setCredentialsMatcher(matcher);
//开启缓存管理
customerRealm.setCacheManager(new EhCacheManager());
customerRealm.setCachingEnabled(true); //开启全局缓存
customerRealm.setAuthenticationCachingEnabled(true); //开启认证缓存
customerRealm.setAuthenticationCacheName("authenticationCache");
customerRealm.setAuthorizationCachingEnabled(true); //开启授权缓存
customerRealm.setAuthorizationCacheName("authorization");
return customerRealm;
}
/**
* 方法名:
* 功能:凭证匹配器
* 描述:指定shiro加密方式和次数
*/
@Bean(name = "customCredentialsMatch")
public CustomCredentialsMatch hashedCredentialsMatch(){
CustomCredentialsMatch hashedCredentialsMatch = new CustomCredentialsMatch();
hashedCredentialsMatch.setHashAlgorithmName("MD5");
hashedCredentialsMatch.setHashIterations(1024);
return hashedCredentialsMatch;
}
@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
return new LifecycleBeanPostProcessor();
}
/**
* 开启shiro aop注解支持,使用代理方式; 所以需要开启代码支持; Controller才能使用@RequiresPermissions
*
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
6.模拟用户登陆
@RequestMapping("/initindex")
public void loginTest(HttpServletRequest request,
HttpServletResponse response){
Subject subject = SecurityUtils.getSubject();
//密码登录
//CustomToken token = new CustomToken("zhangsan",123);
//无密登录
CustomToken token = new CustomToken("zhangsan");
token.setRememberMe(true);
subject.login(token);
}
以上是关于Shiro免密登录的主要内容,如果未能解决你的问题,请参考以下文章
全栈编程系列SpringBoot整合Shiro(含KickoutSessionControlFilter并发在线人数控制以及不生效问题配置启动异常No SecurityManager...)(代码片段