发表于: 2019-12-11 22:06:10
2 1171
今天做了什么:
前台-学生证接口都调试成功.
Spring Boot整合Shiro:
shiro的配置:
@Configuration
public class ShiroConfig {
/**
* 一个过滤器,拦截url
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//必须set项
shiroFilterFactoryBean.setSecurityManager(securityManager);
//设置登录页面
shiroFilterFactoryBean.setLoginUrl("/login");
//设置登录成功跳转页面
shiroFilterFactoryBean.setSuccessUrl("/backDesk");
//权限不足跳转的页面
shiroFilterFactoryBean.setUnauthorizedUrl("/noAuthc");
//拦截器,下面的属性就是配置不会被拦截的url
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问,封装在DefaultWebSecurityManager中
filterChainDefinitionMap.put("/home","anon");
filterChainDefinitionMap.put("/login/0","anon");
filterChainDefinitionMap.put("/register/0","anon");
filterChainDefinitionMap.put("/register/1","anon");
filterChainDefinitionMap.put("/logout","logout");
//设置权限拦截器,当权限为superManager才能访问后台
filterChainDefinitionMap.put("/student/backDesk","authc,perms[/student/backDesk]");
//这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//关联Realm
defaultWebSecurityManager.setRealm(accountRealm());
return defaultWebSecurityManager;
}
/**
* 加入加密配置
* @return
*/
@Bean(name = "credentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
// 散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashAlgorithmName("md5");
// 散列的次数,比如散列两次,相当于 md5(md5(""));
hashedCredentialsMatcher.setHashIterations(2);
// storedCredentialsHexEncoded默认是true,此时用的是密码加密用的是Hex编码;false时用Base64编码
hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
return hashedCredentialsMatcher;
}
/**
* 创建Realm以便调用
* @return
*/
@Bean
public AccountRealm accountRealm() {
AccountRealm accountRealm = new AccountRealm();
// 告诉realm,使用credentialsMatcher加密算法类来验证密文
accountRealm.setCredentialsMatcher(hashedCredentialsMatcher());
accountRealm.setCachingEnabled(false);
return accountRealm;
}
}
定义的Realm:()
public class AccountRealm extends AuthorizingRealm {
@Autowired
private AccountService accountService;
/**
* 用户授权
* 因为暂时没用到授权所以注释了
**/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principalCollection) {
System.out.println("===执行授权===");
//
// Subject subject = SecurityUtils.getSubject();
// Account account = (Account) subject.getPrincipal();
//
// if(account != null){
// SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// // 角色与权限字符串集合
// Collection<String> rolesCollection = new HashSet<>();
// Collection<String> permissionCollection = new HashSet<>();
// // 读取并赋值用户角色与权限
// Set<RoleBean> roles = user.getRole();
// for(RoleBean role : roles){
// rolesCollection.add(role.getName());
// Set<PermissionBean> permissions = role.getPermissions();
// for (PermissionBean permission : permissions){
// premissionCollection.add(permission.getUrl());
// }
// info.addStringPermissions(premissionCollection);
// }
// info.addRoles(rolesCollection);
// return info;
// }
return null;
}
/**
* 用户认证
**/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("开始执行认证");
//从token中获取principal和credentials.相当于账号和密码
String username = (String) authenticationToken.getPrincipal();
String pwd = new String((char[]) authenticationToken.getCredentials());
//根据name从数据库中查user
Account account = accountService.findByName(username);
System.out.println("token.username: "+username);
System.out.println("findByName: "+account);
if (account != null){
// 若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验
//参数1.用户认证的对象(subject.getPrincipal();返回的对象),
//参数2.从数据库根据用户名查询到的用户的密码
//参数3.把当前自定义的realm对象传给SimpleAuthenticationInfo,在配置文件需要注入
System.out.println("return simpleAuthInfo");
return new SimpleAuthenticationInfo(account.getUsername(), account.getPassword(),getName());
}
return null;
}
}
controller:
@PostMapping("/login")
public String login(String username,String password){
//1.根据账密生成token
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
//2.获取当前用户对象
Subject currentUser = SecurityUtils.getSubject();
try {
//3.进行认证
//在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
//每个Realm都能在必要时对提交的AuthenticationTokens作出反应
//所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
log.error("对用户[" + username + "]进行登录验证");
currentUser.login(token);
log.error("验证通过");
}catch (UnknownAccountException uae){
log.error("对用户[" + username + "]进行登录验证..验证未通过,未知的用户");
}catch(IncorrectCredentialsException ice){
log.error("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");
}catch(LockedAccountException lae){
log.error("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");
}catch(ExcessiveAttemptsException eae){
log.error("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");
}catch(AuthenticationException ae){
//通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
log.error("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");
ae.printStackTrace();
}
//验证是否登录成功
if(currentUser.isAuthenticated()){
log.info("用户[" + username + "]登录认证通过");
return "登录成功";
}else{
token.clear();
//重定向到登录处
return "redirect:/login";
}
}
但是还没调通.
报token验证失败错误. username是存在的, password没验证通过, 推测是跟加密有关,明天再弄弄加密.
收获.
问题:
1.SpringBoot 找不到或无法加载主类
2.SpringBoot无法返回视图,报404
3.Spring返回视图报circular view path错误
总结是对spring boot的模板引擎很不熟悉 , 毕竟跟jsp的那一套不同.
明天计划:
继续shiro登录认证, 然后做授权.
评论