【发布时间】:2015-09-29 08:44:59
【问题描述】:
我正在开发一个连接到 Spring-MVC 服务器的 Java 应用程序,使用 Spring-Security 进行身份验证/授权。登录部分有效,我在 Java 应用程序中得到了一个 JSESSIONID,但是当我向安全资源发出请求时,它失败了,Spring-Security 无法找到任何登录用户。我在这里做错了什么?
security-applicationContext.xml:
<security:http pattern="/resources/**" security="none"/>
<security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true">
<security:form-login login-page="/login" login-processing-url="/j_spring_security_check"
default-target-url="/dashboard" always-use-default-target="false"
authentication-failure-url="/denied"/>
<security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService"
token-validity-seconds="1209600" data-source-ref="dataSource"/>
<security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/>
<!--<security:intercept-url pattern="/**" requires-channel="https"/>-->
<security:port-mappings>
<security:port-mapping http="8080" https="8443"/>
</security:port-mappings>
<security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/>
<security:session-management session-fixation-protection="migrateSession">
<security:concurrency-control session-registry-ref="sessionRegistry" max-sessions="5" expired-url="/login"/>
</security:session-management>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="restaurantauthenticationprovider"/>
<security:authentication-provider ref="userauthenticationprovider"/>
</security:authentication-manager>
<beans:bean id="encoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg name="strength" value="11"/>
</beans:bean>
<beans:bean id="restaurantauthenticationprovider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="LoginServiceImpl"/>
<beans:property name="passwordEncoder" ref="encoder"/>
</beans:bean>
<beans:bean id="userauthenticationprovider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="UserLoginServiceImpl"/>
<beans:property name="passwordEncoder" ref="encoder"/>
</beans:bean>
因为我有 2 个表要检查从哪个表登录,所以我有 2 个 DAOAuthenticationProviders。
UserLoginServiceImpl :
@Transactional
@Service("loginuserDetailsService")
public class UserLoginServiceImpl implements UserDetailsService {
@Autowired
private PersonDAO personDAO;
@Autowired
private UserAssembler userAssembler;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
System.out.println("Username is "+username);
Person person = this.personDAO.findPersonByUserName(username.toLowerCase());
if(person == null) { throw new UsernameNotFoundException("Wrong username or password");}
return userAssembler.buildUserFromUserEntity(person);
}
}
汇编器:
@Service("userassembler")
@Transactional
public class UserAssembler {
@Transactional
User buildUserFromUserEntity(Person userEntity){
System.out.println("We are in Userassembler"+userEntity.getEmail());
String username = userEntity.getUsername().toLowerCase();
String password = userEntity.getPassword();
boolean enabled = userEntity.isEnabled();
boolean accountNonExpired = userEntity.isAccountNonExpired();
boolean credentialsNonExpired = userEntity.isCredentialsNonExpired();
boolean accountNonLocked = userEntity.isAccountNonLocked();
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(username,password,enabled,accountNonExpired,credentialsNonExpired,accountNonLocked,authorities);
}
}
以上是配置,现在我将放置失败的其余代码:
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Log.d("Username is ", username);
String jsessionid = rest.execute("http://192.168.178.60:8080/j_spring_security_check", HttpMethod.POST,
new RequestCallback() {
@Override
public void doWithRequest(ClientHttpRequest request) throws IOException {
request.getBody().write(("j_username=" + username + "&j_password=" + password).getBytes());
}
}, new ResponseExtractor<String>() {
@Override
public String extractData(ClientHttpResponse response) throws IOException {
List<String> cookies = response.getHeaders().get("Cookie");
if (cookies == null) {
cookies = response.getHeaders().get("Set-Cookie");
}
String cookie = cookies.get(cookies.size() - 1);
System.out.println("Cookie is " + cookie);
// The method below gets me which user is logged in, and I always get null for Controller method.
reply = rest.getForObject(
"http://192.168.178.60:8080/dashboard", String.class);
int start = cookie.indexOf('=');
int end = cookie.indexOf(';');
return cookie.substring(start + 1, end);
}
});
}
});
thread.start();
更新 最后,有效的代码:
// 我从服务器获取 cookie,我为每个请求手动设置,cookie 是一个静态易失性字符串。
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + StaticRestTemplate.jsessionid);
HttpEntity requestEntity = new HttpEntity(null, requestHeaders);
ResponseEntity rssResponse = rest.exchange(
"http://192.168.178.60:8080/dashboard",
HttpMethod.GET,
requestEntity,
String.class);
String abc = (String) rssResponse.getBody();
【问题讨论】:
-
您的个人服务是什么样的?如果您将方法更改为: String checkWichUserLoggedIn(Principal p) { return p == null 会发生什么?空:p.getName(); }
-
@RobWinch :我把它当作空......因为找不到用户匿名用户。我已经更新了我的主要帖子中的代码,顺便说一句,当我打印身份验证详细信息时,会话 ID 为空。我了解 RestTemplate 在您进行身份验证时会在内部设置一个 cookie,但情况似乎并非如此。
-
你真的得到了一个 JSESSIONID 吗? HTTP 状态码是什么?您使用的是哪个版本的 Spring Security?
-
我在登录时得到 jsessionid 并成功。
标签: java spring spring-mvc spring-security resttemplate