目录
1、添加依赖
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.7.0</version> </dependency>
2、创建不同登录方式的token
邮箱登录
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmailToken implements AuthenticationToken {
private String email;
private String verifyCode;
public EmailToken(String verifyCode) {
this.verifyCode = verifyCode;
}
@Override
public Object getPrincipal() {
return this.email;
}
@Override
public Object getCredentials() {
return this.verifyCode;
}
}
账号密码登录
public class UsernamePasswordToken extends org.apache.shiro.authc.UsernamePasswordToken {
public UsernamePasswordToken(String username, char[] password) {
super(username, password);
}
public UsernamePasswordToken() {
}
public UsernamePasswordToken(String username, String password) {
super(username, password);
}
public UsernamePasswordToken(String username, char[] password, String host) {
super(username, password, host);
}
public UsernamePasswordToken(String username, String password, String host) {
super(username, password, host);
}
public UsernamePasswordToken(String username, char[] password, boolean rememberMe) {
super(username, password, rememberMe);
}
public UsernamePasswordToken(String username, String password, boolean rememberMe) {
super(username, password, rememberMe);
}
public UsernamePasswordToken(String username, char[] password, boolean rememberMe, String host) {
super(username, password, rememberMe, host);
}
public UsernamePasswordToken(String username, String password, boolean rememberMe, String host) {
super(username, password, rememberMe, host);
}
}
3、创建不同的realm
邮箱
public class EmailRealm extends AuthorizingRealm {
@Autowired
StringRedisTemplate stringRedisTemplate;
//shiro内部会调用这个方法来判断执不执行该realm
@Override
public boolean supports(AuthenticationToken token) {
System.out.println(token instanceof EmailToken);
return token instanceof EmailToken;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
EmailToken emailToken = ((EmailToken) authenticationToken);
Boolean isExist = stringRedisTemplate.hasKey(emailToken.getEmail() + "login");
System.out.println(isExist);
if(isExist != null && isExist){
String code = stringRedisTemplate.opsForValue().get(emailToken.getEmail()+"login");
return new SimpleAuthenticationInfo(emailToken.getPrincipal(),
code, this.getName());
}
return null;
}
}
账号密码
public class MyRealm extends AuthorizingRealm {
@Autowired
private PermissionFeign permissionFeign;
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
public boolean supports(AuthenticationToken token) {
System.out.println(token instanceof UsernamePasswordToken);
return token instanceof UsernamePasswordToken;
}
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = authenticationToken.getPrincipal().toString();
SysUser user = permissionFeign.findUserByUserName(username);
if (user!=null){
ByteSource salf = ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(user,user.getPassword(),salf,this.getName());
return info;
}
return null;
}
}
4、创建realm认证策略
在ModularRealmAuthenticator 中,多重验证中,默认的验证策略AtLeastOneSuccessfulStrategy
策略 | 意义 |
---|---|
AllSuccessfulStrategy | 所有都满足的情况 |
AtLeastOneSuccessfulStrategy | 至少一条满足的情况 |
FirstSuccessfulStrategy | 第一条满足的情况 |
可以通过继承ModularRealmAuthenticator 来重新定义获取realm的规则。这里我使用的是默认的。
5、shiro配置类
@Configuration
public class ShiroConfig {
@Bean
public DefaultWebSecurityManager securityManager(){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
securityManager.setRealms(Arrays.asList(realm(),emailRealm()));
return securityManager;
}
@Bean
public Realm realm(){
MyRealm myRealm=new MyRealm();
myRealm.setCredentialsMatcher(credentialsMatcher());
return myRealm;
}
@Bean
public Realm emailRealm(){
EmailRealm emailRealm = new EmailRealm();
return emailRealm;
}
@Bean
public CredentialsMatcher credentialsMatcher(){
HashedCredentialsMatcher credentialsMatcher=new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5");
credentialsMatcher.setHashIterations(1024);
return credentialsMatcher;
}
@Resource
private RedisTemplate redisTemplate;//此处之所以引入是因为LoginFilter中的构造函数使用
@Bean(value = "shiroFilter")
public ShiroFilterFactoryBean filterFactoryBean(){
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager());
//设置拦截规则
HashMap<String,String> map=new HashMap<>();
map.put("/sso/login","anon");
map.put("/sso/emailLogin", "anon");
//配置swigger过滤权限
map.put("/**/*.css","anon");
map.put("/**/*.js","anon");
map.put("/doc.html","anon");
map.put("/swagger-resources","anon");
map.put("/v2/api-docs","anon");
map.put("/**","authc");
factoryBean.setFilterChainDefinitionMap(map);
//设置自定义认证过滤器
HashMap<String, Filter> filterMap=new HashMap<String, Filter>();
filterMap.put("authc",new LoginFilter(redisTemplate));
factoryBean.setFilters(filterMap);
return factoryBean;
}
@Bean //注册filter
public FilterRegistrationBean<Filter> filterRegistrationBean(){
FilterRegistrationBean<Filter> filterRegistrationBean=new FilterRegistrationBean<>();
filterRegistrationBean.setName("shiroFilter");
filterRegistrationBean.setFilter(new DelegatingFilterProxy());
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
//开始shiro注解
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
}