自定义Realm实现认证
Shiro默认使用自带的 IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm。
1,Realm接口
最基础的是Realm接口,CachingRealm负责缓存处理,AuthenticatingRealm负责认证,AuthorizingRealm负责授权,
通常自定义的realm继承AuthorizingRealm
shiro.ini
User.java
package com.sxt.domain;
import java.util.Date;
public class User {
private Integer id;
private String username;
private String pwd;
private Date createtime;
public User() {
}
public User(Integer id, String username, String pwd, Date createtime) {
super();
this.id = id;
this.username = username;
this.pwd = pwd;
this.createtime = createtime;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
}
UserService.java
package com.sxt.service;
import com.sxt.domain.User;
public interface UserService {
/**
* 根据用户名查询用户对象
*/
public User queryUserByUserName(String username);
}
UserServiceImpl.java
package com.sxt.service.imp;
import java.util.Date;
import com.sxt.domain.User;
import com.sxt.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public User queryUserByUserName(String username) {
User user=null;
switch (username) {
case "zhangsan":
user=new User(1, "zhangsan", "123456", new Date());
break;
case "lisi":
user=new User(2, "lisi", "123456", new Date());
break;
case "wangwu":
user=new User(3, "wangwu", "123456", new Date());
break;
}
return user;
}
}
UserRealm.java
package com.sxt.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;
import com.sxt.domain.User;
import com.sxt.service.UserService;
import com.sxt.service.imp.UserServiceImpl;
public class UserRealm extends AuthenticatingRealm {
private UserService userService=new UserServiceImpl();
/**
* 做认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username=token.getPrincipal().toString();
token.getCredentials();
System.out.println(username);
/**
* 以前登陆的逻辑是 把用户和密码全部发到数据库 去匹配
* 在shiro里面是先根据用户名把用户对象查询出来,再来做密码匹配
*/
User user=userService.queryUserByUserName(username);
if(null!=user) {
/**
* 参数说明
* 参数1:可以传到任意对象
* 参数2:从数据库里面查询出来的密码
* 参数3:当前类名
*/
SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(user, user.getPwd(), this.getName());
return info;
}else {
//用户不存在 shiro会抛 UnknowAccountException
return null;
}
}
}
TestAuthenticationApp.java
package com.sxt.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* shiro的认证使用shiro.ini文件
*
*/
@SuppressWarnings("deprecation")
public class TestAuthenticationApp {
// 日志输出工具
private static final transient Logger log = LoggerFactory.getLogger(TestAuthenticationApp.class);
public static void main(String[] args) {
String username = "zhangsan";
String password = "123456";
log.info("My First Apache Shiro Application");
// 1,创建安全管理器的工厂对象 org.apache.shiro.mgt.SecurityManager;
// 不能使用java.lang.SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 2,使用工厂创建安全管理器
DefaultSecurityManager securityManager = (DefaultSecurityManager) factory.getInstance();
// 3,创建UserRealm
// UserRealm realm = new UserRealm();
// 4,给securityManager注入userRealm
// securityManager.setRealm(realm);
// 6,把当前的安全管理器绑定当到线的线程
SecurityUtils.setSecurityManager(securityManager);
// 7,使用SecurityUtils.getSubject得到主体对象
Subject subject = SecurityUtils.getSubject();
// 8,封装用户名和密码
AuthenticationToken token = new UsernamePasswordToken(username, password);
// 9,得到认证
try {
subject.login(token);
System.out.println("认证通过");
Object principal = subject.getPrincipal();
System.out.println(principal);
} catch (IncorrectCredentialsException e) {
System.out.println("密码不正确");
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
}
}
}