spring boot使用自定义Realm
2019-03-18 本文已影响0人
JurlyL
最近做的spring boot项目,我在负责登录相关的功能,所以就学习了下怎么在boot中整合shiro,使用自定义的Realm进行相关的登录验证,记录如下:
首先要引入shiro的起步依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>RELEASE</version>
</dependency>
然后新建一个自定义的Realm类
public class UserRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权逻辑");
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行认证逻辑");
//假设数据库的账号和密码
String name = "jurly";
String password = "111";
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
if(!token.getUsername().equals(name)){
// 抛出账号不存在的异常
throw new UnknownAccountException();
}
//在账号存在的情况下验证密码,如果密码正确就认证成功,不正确会抛IncorrectCredentialsException异常
return new SimpleAuthenticationInfo("",password,"");
}
}
自定义的Realm需要继承AuthorizingRealm类并重写的两个方法,doGetAuthorizationInfo方法用于授权,doGetAuthenticationInfo用于认证。
在此处只记录认证有关的~
SimpleAuthenticationInfo构造器代码如下
public SimpleAuthenticationInfo(Object principal, Object credentials, String realmName) {
this.principals = new SimplePrincipalCollection(principal, realmName);
this.credentials = credentials;
}
只需要传中间的password参数就好,看了源码和网上的一些讲解,但具体原因我还是没整明白...如果有人不小心看到了这里...甚至还知道为什么的话,麻烦赐教一下~
Realm写好以后,就可以用该realm进行shiro配置,配置类代码如下
@Configuration
public class ShiroConfig {
/**
* 创建shiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager")DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//把securityManager注入ShiroFilterFactoryBean
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
Map<String,String> filterMap = new LinkedHashMap<>();
filterMap.put("/toLogin","anon");
filterMap.put("/login","anon");
filterMap.put("/*","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
/**
* 创建securityManager
*/
@Bean(name = "defaultWebSecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
/*******把realm注入securityManager*******/
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
/**
* 获取自定义Realm
* @return
*/
@Bean(name="userRealm")
public UserRealm getUserRealm(){
return new UserRealm();
}
}
shiro配置这里不做详细解释了,重点的两行。。。凸出了。。。主要就是把realm注入securityManager,然后把securityManager注入ShiroFilterFactoryBean,配置一些拦截路径,这样就能用shiro的拦截功能了
然后,就可以使用shiro了
@RequestMapping("/login")
public String login(String name,String password, Model model){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(name,password);
try{
subject.login(token);
return "index";
}catch (UnknownAccountException e){
model.addAttribute("msg","用户名不存在");
return "login";
}catch (IncorrectCredentialsException e){
model.addAttribute("msg","密码错误");
return "login";
}
}
当subject提交login请求的时候,就会交给自定义的realm来处理相关的认证请求~
大体使用就是酱紫...可能描述的不清楚,望见谅~有不明白的地方可以在下方留言,知道SimpleAuthenticationInfo构造器为什么只需要传第二个密码参数的如果看到也麻烦赐教一下,谢谢啦