前端页面用的是freemarker模板+h5,具体报错日志如下:
[DEBUG] 2019-08-14 10:29:58.573 org.nutz.dao.impl.sql.run.NutDaoExecutor.printSQL(NutDaoExecutor.java:388) - SELECT * FROM sys_account WHERE account=? LIMIT 0, 1
| 1 |
|-------|
| admin |
For example:> "SELECT * FROM sys_account WHERE account='admin' LIMIT 0, 1 "
[WARN ] 2019-08-14 10:29:58.574 org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:216) - Authentication failed for token submission [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=false (127.0.0.1)]. Possible unexpected error? (Typical or expected login exceptions should extend from AuthenticationException).
org.nutz.dao.DaoException: java.lang.NullPointerException
at org.nutz.dao.impl.sql.run.NutDaoRunner._runWithoutTransaction(NutDaoRunner.java:140)
at org.nutz.dao.impl.sql.run.NutDaoRunner._run(NutDaoRunner.java:93)
at org.nutz.dao.impl.sql.run.NutDaoRunner.run(NutDaoRunner.java:82)
at org.nutz.dao.impl.DaoSupport.run(DaoSupport.java:240)
at org.nutz.dao.impl.DaoSupport._exec(DaoSupport.java:252)
at org.nutz.dao.impl.NutDao.fetch(NutDao.java:591)
at com.ex.mvc.service.SysAccountService.getAccount(SysAccountService.java:78)
at com.ex.mvc.shiro.realm.SysAccountRealm.doGetAuthenticationInfo(SysAccountRealm.java:115)
at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:568)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
at org.apache.shiro.web.filter.authc.AuthenticatingFilter.executeLogin(AuthenticatingFilter.java:53)
at org.apache.shiro.web.filter.authc.FormAuthenticationFilter.onAccessDenied(FormAuthenticationFilter.java:154)
at org.apache.shiro.web.filter.AccessControlFilter.onAccessDenied(AccessControlFilter.java:133)
at org.apache.shiro.web.filter.AccessControlFilter.onPreHandle(AccessControlFilter.java:162)
at com.ex.mvc.shiro.filter.SysAccountFilter.onPreHandle(SysAccountFilter.java:94)
at org.apache.shiro.web.filter.PathMatchingFilter.isFilterChainContinued(PathMatchingFilter.java:203)
at org.apache.shiro.web.filter.PathMatchingFilter.preHandle(PathMatchingFilter.java:178)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:131)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at org.nutz.plugins.cache.dao.DaoCacheInterceptor._exec(DaoCacheInterceptor.java:28)
at org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:188)
at org.nutz.dao.DaoInterceptorChain.doChain(DaoInterceptorChain.java:66)
at org.nutz.dao.impl.interceptor.DaoLogInterceptor.filter(DaoLogInterceptor.java:22)
at org.nutz.dao.DaoInterceptorChain.doChain(DaoInterceptorChain.java:64)
at org.nutz.dao.DaoInterceptorChain.invoke(DaoInterceptorChain.java:139)
at org.nutz.dao.impl.sql.run.NutDaoRunner.runCallback(NutDaoRunner.java:159)
at org.nutz.dao.impl.sql.run.NutDaoRunner._runWithoutTransaction(NutDaoRunner.java:126)
... 49 more
[DEBUG] 2019-08-14 10:29:58.579 org.apache.shiro.web.servlet.SimpleCookie.addCookieHeader(SimpleCookie.java:226) - Added HttpServletResponse Cookie [rememberMe=deleteMe; Path=/admin; Max-Age=0; Expires=Tue, 13-Aug-2019 02:29:58 GMT]
[DEBUG] 2019-08-14 10:29:58.579 org.apache.shiro.web.filter.authc.FormAuthenticationFilter.onLoginFailure(FormAuthenticationFilter.java:206) - Authentication exception
org.apache.shiro.authc.AuthenticationException: Authentication failed for token submission [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=false (127.0.0.1)]. Possible unexpected error? (Typical or expected login exceptions should extend from AuthenticationException).
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:214)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256)
at org.apache.shiro.web.filter.authc.AuthenticatingFilter.executeLogin(AuthenticatingFilter.java:53)
at org.apache.shiro.web.filter.authc.FormAuthenticationFilter.onAccessDenied(FormAuthenticationFilter.java:154)
at org.apache.shiro.web.filter.AccessControlFilter.onAccessDenied(AccessControlFilter.java:133)
at org.apache.shiro.web.filter.AccessControlFilter.onPreHandle(AccessControlFilter.java:162)
at com.ex.mvc.shiro.filter.SysAccountFilter.onPreHandle(SysAccountFilter.java:94)
at org.apache.shiro.web.filter.PathMatchingFilter.isFilterChainContinued(PathMatchingFilter.java:203)
at org.apache.shiro.web.filter.PathMatchingFilter.preHandle(PathMatchingFilter.java:178)
at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:131)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.nutz.dao.DaoException: java.lang.NullPointerException
at org.nutz.dao.impl.sql.run.NutDaoRunner._runWithoutTransaction(NutDaoRunner.java:140)
at org.nutz.dao.impl.sql.run.NutDaoRunner._run(NutDaoRunner.java:93)
at org.nutz.dao.impl.sql.run.NutDaoRunner.run(NutDaoRunner.java:82)
at org.nutz.dao.impl.DaoSupport.run(DaoSupport.java:240)
at org.nutz.dao.impl.DaoSupport._exec(DaoSupport.java:252)
at org.nutz.dao.impl.NutDao.fetch(NutDao.java:591)
at com.ex.mvc.service.SysAccountService.getAccount(SysAccountService.java:78)
at com.ex.mvc.shiro.realm.SysAccountRealm.doGetAuthenticationInfo(SysAccountRealm.java:115)
at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:568)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
... 38 more
Caused by: java.lang.NullPointerException
at org.nutz.plugins.cache.dao.DaoCacheInterceptor._exec(DaoCacheInterceptor.java:28)
at org.nutz.plugins.cache.dao.CachedNutDaoExecutor.exec(CachedNutDaoExecutor.java:188)
at org.nutz.dao.DaoInterceptorChain.doChain(DaoInterceptorChain.java:66)
at org.nutz.dao.impl.interceptor.DaoLogInterceptor.filter(DaoLogInterceptor.java:22)
at org.nutz.dao.DaoInterceptorChain.doChain(DaoInterceptorChain.java:64)
at org.nutz.dao.DaoInterceptorChain.invoke(DaoInterceptorChain.java:139)
at org.nutz.dao.impl.sql.run.NutDaoRunner.runCallback(NutDaoRunner.java:159)
at org.nutz.dao.impl.sql.run.NutDaoRunner._runWithoutTransaction(NutDaoRunner.java:126)
... 49 more
[DEBUG] 2019-08-14 10:29:58.598 com.ex.mvc.shiro.filter.SysAccountFilter.setFailureAttribute(SysAccountFilter.java:79) - getClass---org.apache.shiro.authc.AuthenticationException
[DEBUG] 2019-08-14 10:29:58.598 com.ex.mvc.shiro.filter.SysAccountFilter.setFailureAttribute(SysAccountFilter.java:80) - setFailureAttribute---: Authentication failed for token submission [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=false (127.0.0.1)]. Possible unexpected error? (Typical or expected login exceptions should extend from AuthenticationException).
自定义的realm代码如下
import com.ex.mvc.constants.SysConsts;
import com.ex.mvc.entity.SysAccount;
import com.ex.mvc.entity.SysPermission;
import com.ex.mvc.entity.SysRole;
import com.ex.mvc.service.AccRolePermService;
import com.ex.mvc.service.SysAccountService;
import com.ex.mvc.util.BaseSysUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.Mvcs;
import java.util.ArrayList;
import java.util.List;
/**
* 当前系统shiro认证的realm
*
* @author wangzd
* @date 2019/8/13 15:15
*/
public class SysAccountRealm extends AuthorizingRealm {
// ShiroFilter先于NutFilter初始化化,所以无法使用注入功能
protected Dao dao;
protected SysAccountService sysAccountService;
protected AccRolePermService accRolePermService;
protected static final Log log = Logs.get();
/**
* 授权信息(角色,权限)
*
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// null usernames are invalid
if (principals == null) {
throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
}
int accountId = (Integer) principals.getPrimaryPrincipal();
log.debug("shiro--授权信息--accountId--: " + accountId);
SysAccount sysAccount = dao().fetch(SysAccount.class, Cnd.where(SysAccount.ACCOUNT_ID, "=", accountId));
if (sysAccount == null) {
return null;
}
if (sysAccount.isLock()) {
throw new LockedAccountException("账号[" + sysAccount.getAccount() + "]已锁定");
}
SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();
// 获取当前登录账户的角色列表
List<SysRole> roleList = accRolePermService().getAccRoles(accountId);
for (SysRole role : roleList) {
// 添加角色
auth.addRole(role.getRoleId());
List<SysPermission> permList = new ArrayList<>();
// 判断如果用户是管理员则默认开启所有权限
if (role.getRoleId().equals(SysConsts.SYS_ROLE)) {
permList = accRolePermService().getAllPerms();
} else {
permList = accRolePermService().getRolePerms(role.getRoleId());
}
// 添加权限
for (SysPermission permission : permList) {
auth.addStringPermission(permission.getPermissionId());
}
}
return auth;
}
/**
* 身份验证信息(账户密码)
*
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
SysAccount loginAcc = dao().fetch(SysAccount.class,Cnd.where(SysAccount.ACCOUNT,"=",upToken.getUsername()));
if (null == loginAcc){
throw new UnknownAccountException(String.format("账户 [%s] 不存在", upToken.getUsername()));
}
if (loginAcc.isLock()) {
throw new LockedAccountException(String.format("账户 [%s] 已锁定", upToken.getUsername()));
}
// 此处 SimpleAccount 的构造方法中,第一个参数就是 principal 第二个参数 credentials 存的是加密后的密码
SimpleAccount account = new SimpleAccount(loginAcc.getAccountId(), loginAcc.getPassword(), getName());
if (Strings.isNotBlank(loginAcc.getSalt())) {
account.setCredentialsSalt(ByteSource.Util.bytes(loginAcc.getSalt()));
}
return account;
}
/**
* 密码校验
* 覆盖父类的验证,直接pass. 在shiro内做验证的话, 出错了都不知道哪里错
*/
@Override
protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
// super.assertCredentialsMatch(token, info);
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
log.debug("getUsername----"+upToken.getUsername());
log.debug("getPassword----"+new String(upToken.getPassword()));
log.debug("getPrincipal----"+upToken.getPrincipal());
log.debug("getCredentials----"+upToken.getCredentials());
log.debug("getHost----"+upToken.getHost());
SimpleAccount account = (SimpleAccount) info;
log.debug("getCredentialsSalt----"+new String(account.getCredentialsSalt().getBytes()));
log.debug("getPrincipals----"+account.getPrincipals().getPrimaryPrincipal());
// 密码的明文(通过token由登录页面的入口传来)
String password = new String(upToken.getPassword());
// 当前登录用户的的密码盐
String salt = new String(account.getCredentialsSalt().getBytes());
// 加密后的密码
String saltPwd = BaseSysUtils.saltPwd(password, salt);
if (!account.getCredentials().toString().equals(saltPwd)) {
throw new IncorrectCredentialsException("账户登录密码错误");
}
}
//---------构造方法-----------
public SysAccountRealm() {
this(null, null);
}
public SysAccountRealm(CacheManager cacheManager) {
this(cacheManager, null);
}
public SysAccountRealm(CredentialsMatcher matcher) {
this(null, matcher);
}
public SysAccountRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
super(cacheManager, matcher);
// 非常非常重要,与SecurityUtils.getSubject().login是对应关系!!!
setAuthenticationTokenClass(UsernamePasswordToken.class);
}
//---------构造方法-----------
public void setDao(Dao dao) {
this.dao = dao;
}
public Dao dao() {
if (dao == null) {
dao = Mvcs.ctx().getDefaultIoc().get(Dao.class, "dao");
// dao = BaseSysUtils.ioc().get(Dao.class, "dao");
return dao;
}
return dao;
}
public SysAccountService sysAccountService() {
if (null == sysAccountService) {
sysAccountService = Mvcs.ctx().getDefaultIoc().get(SysAccountService.class);
}
return sysAccountService;
}
public AccRolePermService accRolePermService() {
if (null == accRolePermService) {
accRolePermService = BaseSysUtils.ioc().get(AccRolePermService.class);
}
return accRolePermService;
}
}
本来如果走到doGetAuthenticationInfo方法,从数据库查不到账户信息的话,应该抛出org.apache.shiro.authc.UnknownAccountException异常,提示账户不存在,但现在抛出的异常是 org.apache.shiro.authc.AuthenticationException,异常信息是从org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:216)里边拼接的信息