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...)(代码片段

CAS登录后回传除了ticket参数以外的其他自定义参数

免密登录-python

guacamole免密登录,guacamole不通过登录界面登录,guacamole指定用户名免密登录

ssh免密登录免提示登录

ssh免密登录免提示登录