【发布时间】:2016-12-18 14:21:00
【问题描述】:
-
用户服务实现:
@Override public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException{ String userID = credential.getNameID().getValue(); logger.info(userID + " is logged in"); List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); authorities.add(authority); List<Attribute> userAttributes = credential.getAttributes(); logger.info("Credential attributes: " + userAttributes); for (int attrIndex = 0; attrIndex < userAttributes.size(); attrIndex++) { Attribute attr = userAttributes.get(attrIndex); List<XMLObject> attrValues = attr.getAttributeValues(); StringBuilder strBuilder = new StringBuilder(); for (int attrValueIndex = 0; attrValueIndex < attrValues.size(); attrValueIndex++) { XMLObject currObj = attrValues.get(attrValueIndex); strBuilder.append(currObj.toString()).append(","); } strBuilder.deleteCharAt(strBuilder.length() - 1); logger.info(attr.getFriendlyName() + ", " + strBuilder.toString()); String samlAttrValue = strBuilder.toString(); switch (attr.getFriendlyName()) { case "userName": samlUserAttribute.setUserName(samlAttrValue); case "email": samlUserAttribute.setEmail(samlAttrValue); break; case "firstName": samlUserAttribute.setFirstName(samlAttrValue); break; case "lastName": samlUserAttribute.setLastName(samlAttrValue); break; case "userType": samlUserAttribute.setUserType(samlAttrValue); break; case "accountName": samlUserAttribute.setAccountName(samlAttrValue); break; case "contactId": samlUserAttribute.setContactId(samlAttrValue); break; default: logger.info("invalid attribute name" + attr.getFriendlyName()); } } logger.info("User details obtained: " + samlUserAttribute); return new SamlUserDTO(userID, "<abc123>", authorities, samlUserAttribute); } -
UserDetails 实现:
private SamlUserAttribute currentUserAttribute; private String password; private final String username; private final Set<GrantedAuthority> authorities; private final boolean accountNonExpired; private final boolean accountNonLocked; private final boolean credentialsNonExpired; private final boolean enabled; .. setter/getter/contructors for userDetails...3.安全配置详情
<security:http entry-point-ref="samlEntryPoint" access-decision-manager-ref="accessDecisionManager" authentication-manager-ref="authenticationManager" use-expressions="true"> <security:intercept-url pattern="/login" access="permitAll"/> <security:intercept-url pattern="/**" access="isFullyAuthenticated()" /> <security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter" /> <security:csrf disabled="true"/> </security:http> <bean id="samlFilter" class="org.springframework.security.web.FilterChainProxy"> <security:filter-chain-map request-matcher="ant"> <security:filter-chain pattern="/**" filters="samlEntryPoint" /> </security:filter-chain-map> </bean> <bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider"> <property name="userDetails" ref="UserServiceImpl" /> <property name="forcePrincipalAsString" value="false" /> </bean> <bean id="UserServiceImpl" class="com.akamai.marketplace.service.impl.common.UserServiceImpl"> </bean>
在点击所需的 URL 时,我可以在浏览器上看到 IDP 重定向发生,IDP 使用所需的断言进行回复,并且登陆 URL 是 /login 但在我的 /login 控制器中,身份验证对象的 UserDetail 尚未填充自定义数据。
-
/登录控制器:
@RequestMapping(path="/login",method = RequestMethod.POST) public ResponseEntity<SamlUserDTO> login() { logger.info("login API reached through IdP."); Authentication userAuthentication = SecurityContextHolder.getContext().getAuthentication(); logger.info("user details: "+userAuthentication.getDetails()); logger.info("user credentials: "+userAuthentication.getCredentials()); logger.info("principal " + userAuthentication.getPrincipal()); SamlUserDTO samlUserDTO1 = (SamlUserDTO) userAuthentication.getPrincipal(); return ResponseEntity.ok(samlUserDTO1); }
日志:
2016-08-11 17:22:16 调试 BaseMessageEncoder:56 - 成功编码消息。 2016-08-11 17:22:16 调试 HttpSessionStorage:93 - 将消息 a399ehchh04afi304hih7e49fd791g2 存储到会话 someValue
2016-08-11 17:22:16 信息 SAMLDefaultLogger:127 - AuthNRequest;SUCCESS;someIP;SP-entityId;Idp-entityId;;;
2016-08-11 17:22:37 INFO UserController:18 - 通过 IdP 访问登录 API。
2016-08-11 17:22:37 INFO UserController:20 - 用户详细信息:org.springframework.security.web.authentication.WebAuthenticationDetails@ffffa64e:RemoteIpAddress:Idp-IpAddress; SessionId:一些值
2016-08-11 17:22:37 INFO UserController:21 - 用户凭据:
2016-08-11 17:22:37 INFO UserController:22 - 主体anonymousUser 2016-08-11 17:22:37 DEBUG ExceptionHandlerExceptionResolver:133 - 从处理程序 [public org.springframework.http.ResponseEntity com.akamai.marketplace.controller.UserController.login()] 解决异常:java.lang.ClassCastException:java .lang.String 不能转换为 controller.model.SamlUserDTO
2016-08-11 17:22:37 调试 ExceptionHandlerExceptionResolver:361 - 调用 @ExceptionHandler 方法:公共 org.springframework.http.ResponseEntity RESTExceptionHandler.handleExeption(java.lang.Exception) 2016-08-11 17:22:37 错误 RESTExceptionHandler:60 - 异常处理程序捕获的异常: java.lang.ClassCastException:java.lang.String 无法转换为 package.SamlUserDTO
【问题讨论】:
标签: spring-boot saml-2.0 spring-saml