配置类代码:
@Configuration
public class ShiroConfiguration {
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(getJPARealm());
return securityManager;
}
@Bean
public JPARealm getJPARealm(){
JPARealm myShiroRealm = new JPARealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
}
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = newAuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
部分代码用颜色标识如下:
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(getJPARealm());
return securityManager;
}
@Bean
public JPARealm getJPARealm(){
JPARealm myShiroRealm = new JPARealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
}
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = newAuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
hashedCredentialsMatcher() 指定了 加密算法为md5,并且进行2次加密。(插一句,springsecurity较新的版本不支持md5了)
还有同颜色部分值得细品。
注册时的操作
String salt = new SecureRandomNumberGenerator().nextBytes().toString();
int times = 2;
String algorithmName = "md5";
String encodedPassword = new SimpleHash(algorithmName, password, salt, times).toString();
user.setSalt(salt);
user.setPassword(encodedPassword);
userService.add(user);
登录时的操作
@PostMapping("/forelogin")
public Object login(@RequestBody User userParam, HttpSession session) {
String name = userParam.getName();
name = HtmlUtils.htmlEscape(name);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(name, userParam.getPassword());
try {
subject.login(token);
User user = userService.getByName(name);
// subject.getSession().setAttribute("user", user);
session.setAttribute("user", user);
return Result.success();
} catch (AuthenticationException e) {
String message ="账号密码错误";
return Result.fail(message);
}
}
注释掉的部分为原来用session完成了注册登录拦截退出,现在整合了shiro。
紫色代码细品。
拦截器
拦截器里会判断是否登陆,切换为 Shiro 方式:
主要利用这个 subject.isAuthenticated()
Subject subject = SecurityUtils.getSubject();
if(!subject.isAuthenticated()) {
httpServletResponse.sendRedirect("login");
return false;
}
Realm
接下来是realm
public class DatabaseRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo s = new SimpleAuthorizationInfo();
return s;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName = token.getPrincipal().toString();
User user = userService.getByName(userName);
String passwordInDB = user.getPassword();
String salt = user.getSalt();
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, passwordInDB, ByteSource.Util.bytes(salt),
getName());
return authenticationInfo;
}
上面这个类就是realm
刚开始学shiro时,一开始的步骤就是去配置shiro.ini,里面会配置
DatabaseRealm的位置,
还为DatabaseRealm 指定credentialsMatcher,其中就指定了算法是 md5, 次数为2
该项目里就直接使用配置类的形式,用configuration注解将该类注册为bean,再将该类的方法上写bean注解。配置类的方式和shiro.ini的方式是等价的。