我这边配置了security,验证成功后,不知道为什么没有把userdetails保存到SecurityContext中。
但是
request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");能获取到userDetails.
这个是为什么?
网络上有说,我是因为配置了 security="none"所以不会放到SecurityContext中,但是实际上我只对登录的放行,其他的都需要过滤。具体我还是贴一下关键代码。
XML配置
<sec:http pattern="/login/login.do" security="none" />
<sec:http pattern="error.jsp" security="none" />
<sec:http pattern="index.jsp" security="none" />
<sec:http pattern="/syscode/type.do" security="none" />
<sec:http pattern="/login/loginpage.do" security="none" />
<sec:http use-expressions="true" auto-config="true" access-denied-page="/views/accessDenied.jsp">
<sec:form-login login-page="/login/loginpage.do"
authentication-failure-url="/index.jsp"
default-target-url="/login/main.do"
/>
<sec:logout invalidate-session="true" logout-success-url="/index.jsp" />
<!--<检测失效的sessionId,超时时定位到另外一个URL
<sec:session-management invalid-session-url="/views/sessionTimeout.jsp" />-->
<sec:custom-filter ref="worktimesLoginProcessingFilter" before="FORM_LOGIN_FILTER" />
<sec:custom-filter ref="worktimesSessionFilter" before="CONCURRENT_SESSION_FILTER" />
</sec:http>
<bean class="org.springframework.security.authentication.event.LoggerListener" />
<bean id="worktimesLoginProcessingFilter" class="com.worktimes.core.security.WorktimesLoginProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler" />
<property name="sessionAuthenticationStrategy" ref="sas" />
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
</bean>XML的配置很简单,
关键是配置了一个worktimesLoginProcessingFilter的过滤器,实现AbstractUserDetailsAuthenticationProvider接口。
在WorktimesAuthenticationProvider中,装配WorktimesUsernamePasswordAuthenticationToken后,保存到AuthenticationManager中,具体代码如下:@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException,
IOException, ServletException { String loginType = request.getParameter("loginType");
String username = request.getParameter("account");
String password = request.getParameter("password");
if(loginType == null){
throw new CaptchaException("loginType is null!");
}
if("0".equals(loginType)){
loginType = Constants.NormalUser;
}else{
loginType = Constants.SystemUser;
}
WorktimesUsernamePasswordAuthenticationToken authRequest = null;
this.logger.info("Captcha enabled!");
//验证码
String captchaValue = (String)request.getSession().getAttribute("Rand");
String captchaReq = request.getParameter("captcha");
if (!captchaReq.equals(captchaValue)) {
throw new CaptchaException("Bad captcha!");
}
request.getSession().removeAttribute("Rand");
request.getSession().setAttribute("username", username);
//装配UsernamePasswordAuthenticationToken
authRequest = new WorktimesUsernamePasswordAuthenticationToken(username, password, loginType);
authRequest.setLoginType(loginType);
authRequest.setUserIP(CommonFunction.getIpAddr(request));
//保存到AuthenticationManager中
return getAuthenticationManager().authenticate(authRequest);
}我看文档,到这里就会把WorktimesUsernamePasswordAuthenticationToken放进SecurityContext中。不知道对不对...
在这步执行完后,spring security会进行用户名密码验证,实现AbstractUserDetailsAuthenticationProvider接口@Override
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
WorktimesUsernamePasswordAuthenticationToken worktimesAuthentication = (WorktimesUsernamePasswordAuthenticationToken) authentication;
String presentedPassword = worktimesAuthentication.getCredentials().toString();
if(!presentedPassword.equals(userDetails.getPassword())){
this.logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException("Bad credentials");
}
} @Override
protected UserDetails retrieveUser(String username,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
WorktimesUsernamePasswordAuthenticationToken worktimesAuthentication = (WorktimesUsernamePasswordAuthenticationToken) authentication;
userDetailsService.loginType=worktimesAuthentication.getLoginType();
WorktimesUserInfo userInfo = (WorktimesUserInfo)userDetailsService.loadUserByUsername(worktimesAuthentication.getName());
if(userInfo.getStatus().equals("1")){
throw new AccountExpiredException("用户已注销!");
}
return userInfo;
}先执行retrieveUser获取User对象,通过userDetailsService到数据库查询我这边的帐户,这步代码就不贴了,无非是查数据库数据,填充WorktimesUserInfo。对了,WorktimesUserInfo是要继承User。然后账号没问题,springsecurity会执行additionalAuthenticationChecks检查用户密码是否正确。我到这边密码也是正常的。
关键代码就是这些,最后执行成功后,页面跳转根据XML文件中配置的authenticationSuccessHandler跳转到/login/main.do,这个也是正常。接下来获取用户就有问题了,public static WorktimesUserInfo getLoginUser(){
Object userInfo = null;
SecurityContext securityContext = SecurityContextHolder.getContext();
System.out.println("认证成功后获取securityContext:"+securityContext);
System.out.println("认证成功后获取getAuthentication:"+securityContext.getAuthentication());
if(securityContext != null && securityContext.getAuthentication() !=null ){
userInfo = securityContext.getAuthentication().getPrincipal();
if(userInfo instanceof WorktimesUserInfo){
return (WorktimesUserInfo) userInfo;
}
}
return null;
}定义一个方法获取用户信息,但是securityContext正常,能打印出来值,但是
securityContext.getAuthentication()是null。这个就郁闷了,不知道什么情况,查了很多资料都没办法解决........
还请大神解答.....
但是
request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");能获取到userDetails.
这个是为什么?
网络上有说,我是因为配置了 security="none"所以不会放到SecurityContext中,但是实际上我只对登录的放行,其他的都需要过滤。具体我还是贴一下关键代码。
XML配置
<sec:http pattern="/login/login.do" security="none" />
<sec:http pattern="error.jsp" security="none" />
<sec:http pattern="index.jsp" security="none" />
<sec:http pattern="/syscode/type.do" security="none" />
<sec:http pattern="/login/loginpage.do" security="none" />
<sec:http use-expressions="true" auto-config="true" access-denied-page="/views/accessDenied.jsp">
<sec:form-login login-page="/login/loginpage.do"
authentication-failure-url="/index.jsp"
default-target-url="/login/main.do"
/>
<sec:logout invalidate-session="true" logout-success-url="/index.jsp" />
<!--<检测失效的sessionId,超时时定位到另外一个URL
<sec:session-management invalid-session-url="/views/sessionTimeout.jsp" />-->
<sec:custom-filter ref="worktimesLoginProcessingFilter" before="FORM_LOGIN_FILTER" />
<sec:custom-filter ref="worktimesSessionFilter" before="CONCURRENT_SESSION_FILTER" />
</sec:http>
<bean class="org.springframework.security.authentication.event.LoggerListener" />
<bean id="worktimesLoginProcessingFilter" class="com.worktimes.core.security.WorktimesLoginProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler" />
<property name="sessionAuthenticationStrategy" ref="sas" />
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
</bean>XML的配置很简单,
关键是配置了一个worktimesLoginProcessingFilter的过滤器,实现AbstractUserDetailsAuthenticationProvider接口。
在WorktimesAuthenticationProvider中,装配WorktimesUsernamePasswordAuthenticationToken后,保存到AuthenticationManager中,具体代码如下:@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException,
IOException, ServletException { String loginType = request.getParameter("loginType");
String username = request.getParameter("account");
String password = request.getParameter("password");
if(loginType == null){
throw new CaptchaException("loginType is null!");
}
if("0".equals(loginType)){
loginType = Constants.NormalUser;
}else{
loginType = Constants.SystemUser;
}
WorktimesUsernamePasswordAuthenticationToken authRequest = null;
this.logger.info("Captcha enabled!");
//验证码
String captchaValue = (String)request.getSession().getAttribute("Rand");
String captchaReq = request.getParameter("captcha");
if (!captchaReq.equals(captchaValue)) {
throw new CaptchaException("Bad captcha!");
}
request.getSession().removeAttribute("Rand");
request.getSession().setAttribute("username", username);
//装配UsernamePasswordAuthenticationToken
authRequest = new WorktimesUsernamePasswordAuthenticationToken(username, password, loginType);
authRequest.setLoginType(loginType);
authRequest.setUserIP(CommonFunction.getIpAddr(request));
//保存到AuthenticationManager中
return getAuthenticationManager().authenticate(authRequest);
}我看文档,到这里就会把WorktimesUsernamePasswordAuthenticationToken放进SecurityContext中。不知道对不对...
在这步执行完后,spring security会进行用户名密码验证,实现AbstractUserDetailsAuthenticationProvider接口@Override
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
WorktimesUsernamePasswordAuthenticationToken worktimesAuthentication = (WorktimesUsernamePasswordAuthenticationToken) authentication;
String presentedPassword = worktimesAuthentication.getCredentials().toString();
if(!presentedPassword.equals(userDetails.getPassword())){
this.logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException("Bad credentials");
}
} @Override
protected UserDetails retrieveUser(String username,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
WorktimesUsernamePasswordAuthenticationToken worktimesAuthentication = (WorktimesUsernamePasswordAuthenticationToken) authentication;
userDetailsService.loginType=worktimesAuthentication.getLoginType();
WorktimesUserInfo userInfo = (WorktimesUserInfo)userDetailsService.loadUserByUsername(worktimesAuthentication.getName());
if(userInfo.getStatus().equals("1")){
throw new AccountExpiredException("用户已注销!");
}
return userInfo;
}先执行retrieveUser获取User对象,通过userDetailsService到数据库查询我这边的帐户,这步代码就不贴了,无非是查数据库数据,填充WorktimesUserInfo。对了,WorktimesUserInfo是要继承User。然后账号没问题,springsecurity会执行additionalAuthenticationChecks检查用户密码是否正确。我到这边密码也是正常的。
关键代码就是这些,最后执行成功后,页面跳转根据XML文件中配置的authenticationSuccessHandler跳转到/login/main.do,这个也是正常。接下来获取用户就有问题了,public static WorktimesUserInfo getLoginUser(){
Object userInfo = null;
SecurityContext securityContext = SecurityContextHolder.getContext();
System.out.println("认证成功后获取securityContext:"+securityContext);
System.out.println("认证成功后获取getAuthentication:"+securityContext.getAuthentication());
if(securityContext != null && securityContext.getAuthentication() !=null ){
userInfo = securityContext.getAuthentication().getPrincipal();
if(userInfo instanceof WorktimesUserInfo){
return (WorktimesUserInfo) userInfo;
}
}
return null;
}定义一个方法获取用户信息,但是securityContext正常,能打印出来值,但是
securityContext.getAuthentication()是null。这个就郁闷了,不知道什么情况,查了很多资料都没办法解决........
还请大神解答.....
解决方案 »
- jsp怎么遍历2个list?
- Ext的下拉框不管选什么都是第一项。怎么解决?急!!!
- java求助,tomcat启动问题----急急急
- 求struts分页代码和中文乱码处理方法
- tomcat连接Access数据库问题。
- 请教,win下用myeclipse开发,运行环境为linux+jboss+mysql,该怎么测试代码呢
- JSP首页怎样自动调用servlet?
- 请问如何保护网站的目录不被访问,只能打开指定的页面,不能打开目录;如何在地址栏里只能看到网络地址,而看不到具体的页面文件名?
- 关于sql语句的连接问题!困绕了我一天啦,郁闷ing!
- 关于XML的问题?
- SpringBoot应用的启动与关闭监听事件
- 返回一个ModelAndView时,竟然根据ModelAndView中设置的viewName自动转发了,然后触发了另外一个方法,由于入参类型不对导致了报错
现在有个新的问题
登录页面login.jsp
如果是用form表单的submit提交,则获取不到文本框的值。var url = appContext+'/j_spring_security_check';
var formObj = $("#loginForm")[0];
formObj.action = url;
$.messager.progress('close');
formObj.submit();然后public class WorktimesLoginProcessingFilter extends AbstractAuthenticationProcessingFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException,
IOException, ServletException {
String loginType = request.getParameter("loginType");
String username = request.getParameter("account");
String password = request.getParameter("password");
System.out.println("loginType:"+loginType);
System.out.println("username:"+username);
System.out.println("password:"+password);
//余下代码略....
}
}打印出来全是null
把你spring secuirty拦截配置那一段发一下
把你spring secuirty拦截配置那一段发一下
我只贴一下重点部分,中间乱七八糟的就不贴了<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring/applicationContext.xml,
classpath:config/spring/datasource.xml,
classpath:config/spring/worktimes-security.xml
</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/j_spring_security_check</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/j_spring_security_logout</url-pattern>
</filter-mapping>
我配置在login-processing-url中也是不行的。<sec:form-login login-page="/login/loginpage.do"
authentication-failure-url="/index.jsp"
login-processing-url="/j_spring_security_check"
default-target-url="/login/main.do"/>