项目场景:

项目采用spring boot+shiro+cas配置,由于数据库原因,登录时认证失败,记录一下解决过程。


问题描述:

cas验证用户成功后,到shiro自定义的realm中执行doGetAuthenticationInfo方法时,抛出NullPointerException异常,异常信息如下:

1
2
3
[http-nio-8088-exec-9] WARN o.a.s.a.AbstractAuthenticator - [authenticate.2161 - Authentication failed for token submission [io.buji.pac4j.token.Pac4jTokenC38e5bc461. Possible unexpected error? (Typical or expected login exce ptions should extend from AuthenticationException).

java.lang-NullPointerException:null

原因分析:

数据库因素:

导致shiro登录认证失败的因素有很多,但其实数据库占很大一部分原因,检查一下数据库是否启动,连接配置是否正确,mabatis的mapperxml配置文件写错是否写错等;

根据报错信息NullPointerException:null,判断大概是因为未查询到数据导致,分为两种情况:

1、根据用户名或登录名未查询到密码导致,shiro登录认证是先根据用户名或登录名查询出用户的账号密码等信息保存到SimpleAuthenticationInfo中,试图登录的用户信息保存到UsernamePasswordToken中,然后进行对比,没有密码肯定报错。

2、数据库没有此用户,查询不到用户。


解决方案:

数据库添加:

1、查询的sql语句结果中添加密码字段;

2、在进行根据用户名或登录名查询登录用户之前添加用户信息,数据库添加用户后,认证成功,错误解决。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)

throws AuthenticationException

{

final Pac4jToken pac4jToken = (Pac4jToken) authenticationToken;

final List<CommonProfile> commonProfileList = pac4jToken.getProfiles();

final CommonProfile commonProfile = commonProfileList.get(0);

Map<String,Object> map = commonProfile.getAttributes();

String loginName = (String) map.get("accountID");

String userName = (String) map.get("realName");

int count = userService.selectUser(loginName,userName);

if (count<1){

User user = new User();

user.setLoginName(loginName);

user.setUserName(userName);

int addUser = userService.insertCasUser(user);

}

String username = commonProfile.getId()+1;

User user = null;

try

{

user = loginService.casLogin(username);

}

catch (Exception e)

{

log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());

throw new AuthenticationException(e.getMessage(), e);

}

return new SimpleAuthenticationInfo(user, commonProfileList.hashCode(), getName());

}