- 浏览: 139455 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (152)
- 异常以及异常处理框架探析 (1)
- java语法 (18)
- 职场生活 (8)
- js前端 (9)
- Tomcat (8)
- java架构 (23)
- .Net (2)
- Linux (4)
- Spring (6)
- Nginx (7)
- 设计模式 (3)
- JVM (4)
- 数据库 (2)
- 智力题 (1)
- SVN (1)
- Maven (3)
- MYSQL (5)
- java线程池2-任务队列的规则 (1)
- 英语学习 (1)
- 面试题 (7)
- MyBatis (2)
- 并发 (3)
- Memcache (2)
- XML (1)
- Hadoop (1)
- Web容器 (1)
- Struts2 (2)
- 产品运营 (1)
- 安全 (1)
- Mongodb (1)
- Shell (0)
- 恋爱 (1)
- 简单对象访问协议 (1)
- mybatis优化(转) (1)
- 算法 (1)
- Redis (2)
- Spring MVC数据绑定大全 (1)
- 错误搜集 (1)
- IDEA (1)
最新评论
-
sunshine_love:
故事里的事说是就是不是也是 故事里的事说不是就不是是也不是 故 ...
在这个变化的年代,IT人的方向在哪里?看两个故事
Spring Security 自定义登录验证与自定义回调地址
博客分类: spring
securityspring
Java代码
1 配置文件 security-ns.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
//需要过滤不被拦截的请求
<security:http pattern="/openapi/**" security="none" />
<security:http pattern="/useraccounts/userprofile.json" security="none" />
<security:http pattern="/useraccounts/register**" security="none" />
//entry-point-ref 配置自定义登录
<security:http auto-config="false" entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/backManage/**" access="ROLE_BACK_USER" />
<security:intercept-url pattern="/mall/**" access="ROLE_BACK_USER" />
<security:intercept-url pattern="/thirdUser/**" access="ROLE_USER" />
<security:intercept-url pattern="/useraccounts/**" access="ROLE_USER" />
<security:intercept-url pattern="/cart/**.html" access="ROLE_USER" />
<security:intercept-url pattern="/ticket/**" access="ROLE_USER,ROLE_BACK_USER" />
<security:intercept-url pattern="/order/**" access="ROLE_USER" />
<security:intercept-url pattern="/comment/**" access="ROLE_USER" />
<security:intercept-url pattern="/personal/**" access="ROLE_USER" />
<security:intercept-url pattern="/favorite/**" access="ROLE_USER" />
//需要替换的Filter顺序,配置自定义custom-filter时必须蔣auto-config="false",不然会报已经存在同样的过滤器错误
<security:custom-filter ref="myLoginFilter" position="FORM_LOGIN_FILTER" />
//登出配置
<security:logout logout-success-url="${local.service.url}"/>
</security:http>
//密码加密工具类
<bean id="encoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/>
//认证管理器
<security:authentication-manager alias="authenticationManager">
//UserDetailsService实现 主要用于用户的查询
<security:authentication-provider user-service-ref="userLoginService">
<security:password-encoder ref="encoder">
</security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="myLoginFilter" class="com.sale114.www.sercurity.MyUsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureHandler" ref="failureHandler"/>
<property name="authenticationSuccessHandler" ref="successHandler"/>
</bean>
//成功登录后
<bean id="successHandler" class="com.sale114.www.sercurity.MySavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="${local.service.url}"/>
</bean>
//登录失败
<bean id="failureHandler" class="com.sale114.www.sercurity.MySimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="${local.service.url}/login.html?validated=false"/>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="${local.service.url}/login.html" />
</bean>
</beans>
2 UserLoginServiceImpl 查询用户实现类
@Named("userLoginService")
public class UserLoginServiceImpl implements UserDetailsService ,LoginService{
@Inject
private UserLoginDAO userLoginDAO;
@Override
public WrappedUserLogin getUserLogin() {
try {
WrappedUserLogin wrappedUserLogin = (WrappedUserLogin) SecurityContextHolder
.getContext().getAuthentication().getPrincipal();
return wrappedUserLogin;
} catch (Exception e) {
return null;
}
}
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
System.out.println("用户名-------------"+username);
UserLogin userLogin = null;
if(username != null && !"".equals(username)&& username.indexOf("@") > 0){
userLogin = userLoginDAO.findByEmail(username);
username = userLogin.getNick();
}else{
userLogin = userLoginDAO.findByNick(username);
}
System.out.println("user is null ---"+userLogin.getUserType());
String nick = userLogin.getNick();
String email = userLogin.getEmail();
String mobile = userLogin.getMobile();
int userType = userLogin.getUserType();
List<GrantedAuthority> resultAuths = new ArrayList<GrantedAuthority>();
// 前台用户
if (userType == 1) {
resultAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
} else {
resultAuths.add(new SimpleGrantedAuthority("ROLE_BACK_USER"));
}
return new WrappedUserLogin(userLogin.getId(), email, nick, mobile, userLogin.getPassword(), userType,resultAuths);
}
}
3 重写用户名密码验证
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
//用户名
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
//密码
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
//需要回调的URL 自定义参数
public static final String SPRING_SECURITY_FORM_REDERICT_KEY = "spring-security-redirect";
/**
* @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}
*/
@Deprecated
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private String redirectParameter = SPRING_SECURITY_FORM_REDERICT_KEY;
private boolean postOnly = true;
//~ Constructors ===================================================================================================
public MyUsernamePasswordAuthenticationFilter() {
super();
}
//~ Methods ========================================================================================================
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
String redirectUrl = obtainRedercitUrl(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
//自定义回调URL,若存在则放入Session
if(redirectUrl != null && !"".equals(redirectUrl)){
request.getSession().setAttribute("callCustomRediretUrl", redirectUrl);
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
/**
* Enables subclasses to override the composition of the password, such as by including additional values
* and a separator.<p>This might be used for example if a postcode/zipcode was required in addition to the
* password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The
* <code>AuthenticationDao</code> will need to generate the expected password in a corresponding manner.</p>
*
* @param request so that request attributes can be retrieved
*
* @return the password that will be presented in the <code>Authentication</code> request token to the
* <code>AuthenticationManager</code>
*/
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
/**
* Enables subclasses to override the composition of the username, such as by including additional values
* and a separator.
*
* @param request so that request attributes can be retrieved
*
* @return the username that will be presented in the <code>Authentication</code> request token to the
* <code>AuthenticationManager</code>
*/
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
protected String obtainRedercitUrl(HttpServletRequest request) {
return request.getParameter(redirectParameter);
}
/**
* Provided so that subclasses may configure what is put into the authentication request's details
* property.
*
* @param request that an authentication request is being created for
* @param authRequest the authentication request object that should have its details set
*/
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
/**
* Sets the parameter name which will be used to obtain the username from the login request.
*
* @param usernameParameter the parameter name. Defaults to "j_username".
*/
public void setUsernameParameter(String usernameParameter) {
Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
this.usernameParameter = usernameParameter;
}
/**
* Sets the parameter name which will be used to obtain the password from the login request..
*
* @param passwordParameter the parameter name. Defaults to "j_password".
*/
public void setPasswordParameter(String passwordParameter) {
Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
this.passwordParameter = passwordParameter;
}
/**
* Defines whether only HTTP POST requests will be allowed by this filter.
* If set to true, and an authentication request is received which is not a POST request, an exception will
* be raised immediately and authentication will not be attempted. The <tt>unsuccessfulAuthentication()</tt> method
* will be called as if handling a failed authentication.
* <p>
* Defaults to <tt>true</tt> but may be overridden by subclasses.
*/
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
}
4 SimpleUrlAuthenticationSuccessHandler重写
public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{
@Value(value = "${local.service.url}")
private String LOCAL_SERVER_URL;
protected final Log logger = LogFactory.getLog(this.getClass());
private RequestCache requestCache = new HttpSessionRequestCache();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
SavedRequest savedRequest = requestCache.getRequest(request, response);
if (savedRequest == null) {
System.out.println("savedRequest is null ");
//用户判断是否要使用上次通过session里缓存的回调URL地址
int flag = 0;
//通过提交登录请求传递需要回调的URL callCustomRediretUrl
if(request.getSession().getAttribute("callCustomRediretUrl") != null && !"".equals(request.getSession().getAttribute("callCustomRediretUrl"))){
String url = String.valueOf(request.getSession().getAttribute("callCustomRediretUrl"));
//若session 存在则需要使用自定义回调的URL 而不是缓存的URL
super.setDefaultTargetUrl(url);
super.setAlwaysUseDefaultTargetUrl(true);
flag = 1;
request.getSession().setAttribute("callCustomRediretUrl", "");
}
//重设置默认URL为主页地址
if(flag == 0){
super.setDefaultTargetUrl(LOCAL_SERVER_URL);
}
super.onAuthenticationSuccess(request, response, authentication);
return;
}
//targetUrlParameter 是否存在
String targetUrlParameter = getTargetUrlParameter();
if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
requestCache.removeRequest(request, response);
super.setAlwaysUseDefaultTargetUrl(false);
super.setDefaultTargetUrl("/");
super.onAuthenticationSuccess(request, response, authentication);
return;
}
//清除属性
clearAuthenticationAttributes(request);
// Use the DefaultSavedRequest URL
String targetUrl = savedRequest.getRedirectUrl();
logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
if(targetUrl != null && "".equals(targetUrl)){
targetUrl = LOCAL_SERVER_URL;
}
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
public void setRequestCache(RequestCache requestCache) {
this.requestCache = requestCache;
}
}
5 认证失败控制类重写
/**
* <tt>AuthenticationFailureHandler</tt> which performs a redirect to the value of the {@link #setDefaultFailureUrl
* defaultFailureUrl} property when the <tt>onAuthenticationFailure</tt> method is called.
* If the property has not been set it will send a 401 response to the client, with the error message from the
* <tt>AuthenticationException</tt> which caused the failure.
* <p>
* If the {@code useForward} property is set, a {@code RequestDispatcher.forward} call will be made to
* the destination instead of a redirect.
*
* @author Luke Taylor
* @since 3.0
*/
public class MySimpleUrlAuthenticationFailureHandler implements AuthenticationFailureHandler{
protected final Log logger = LogFactory.getLog(getClass());
private String defaultFailureUrl;
private boolean forwardToDestination = false;
private boolean allowSessionCreation = true;
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Value(value = "${local.service.url}")
private String LOCAL_SERVER_URL;
public MySimpleUrlAuthenticationFailureHandler() {
}
public MySimpleUrlAuthenticationFailureHandler(String defaultFailureUrl) {
setDefaultFailureUrl(defaultFailureUrl);
}
/**
* Performs the redirect or forward to the {@code defaultFailureUrl} if set, otherwise returns a 401 error code.
* <p>
* If redirecting or forwarding, {@code saveException} will be called to cache the exception for use in
* the target view.
*/
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
//认证失败区别前后台:LOGIN URL
if(request.getParameter("spring-security-redirect") != null){
request.getSession().setAttribute("callUrlFailure", request.getParameter("spring-security-redirect"));
}
//若有loginUrl 则重定向到后台登录界面
if(request.getParameter("loginUrl") != null && !"".equals(request.getParameter("loginUrl"))){
defaultFailureUrl = LOCAL_SERVER_URL+"/backlogin.html?validated=false";
}
//defaultFailureUrl 默认的认证失败回调URL
if (defaultFailureUrl == null) {
logger.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage());
} else {
saveException(request, exception);
if (forwardToDestination) {
logger.debug("Forwarding to " + defaultFailureUrl);
request.getRequestDispatcher(defaultFailureUrl).forward(request, response);
} else {
logger.debug("Redirecting to " + defaultFailureUrl);
redirectStrategy.sendRedirect(request, response, defaultFailureUrl);
}
}
}
/**
* Caches the {@code AuthenticationException} for use in view rendering.
* <p>
* If {@code forwardToDestination} is set to true, request scope will be used, otherwise it will attempt to store
* the exception in the session. If there is no session and {@code allowSessionCreation} is {@code true} a session
* will be created. Otherwise the exception will not be stored.
*/
protected final void saveException(HttpServletRequest request, AuthenticationException exception) {
if (forwardToDestination) {
request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
} else {
HttpSession session = request.getSession(false);
if (session != null || allowSessionCreation) {
request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
}
}
}
/**
* The URL which will be used as the failure destination.
*
* @param defaultFailureUrl the failure URL, for example "/loginFailed.jsp".
*/
public void setDefaultFailureUrl(String defaultFailureUrl) {
this.defaultFailureUrl = defaultFailureUrl;
}
protected boolean isUseForward() {
return forwardToDestination;
}
/**
* If set to <tt>true</tt>, performs a forward to the failure destination URL instead of a redirect. Defaults to
* <tt>false</tt>.
*/
public void setUseForward(boolean forwardToDestination) {
this.forwardToDestination = forwardToDestination;
}
/**
* Allows overriding of the behaviour when redirecting to a target URL.
*/
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
protected RedirectStrategy getRedirectStrategy() {
return redirectStrategy;
}
protected boolean isAllowSessionCreation() {
return allowSessionCreation;
}
public void setAllowSessionCreation(boolean allowSessionCreation) {
this.allowSessionCreation = allowSessionCreation;
}
}
6 登录Controller和页面省略
博客分类: spring
securityspring
Java代码
1 配置文件 security-ns.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
//需要过滤不被拦截的请求
<security:http pattern="/openapi/**" security="none" />
<security:http pattern="/useraccounts/userprofile.json" security="none" />
<security:http pattern="/useraccounts/register**" security="none" />
//entry-point-ref 配置自定义登录
<security:http auto-config="false" entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/backManage/**" access="ROLE_BACK_USER" />
<security:intercept-url pattern="/mall/**" access="ROLE_BACK_USER" />
<security:intercept-url pattern="/thirdUser/**" access="ROLE_USER" />
<security:intercept-url pattern="/useraccounts/**" access="ROLE_USER" />
<security:intercept-url pattern="/cart/**.html" access="ROLE_USER" />
<security:intercept-url pattern="/ticket/**" access="ROLE_USER,ROLE_BACK_USER" />
<security:intercept-url pattern="/order/**" access="ROLE_USER" />
<security:intercept-url pattern="/comment/**" access="ROLE_USER" />
<security:intercept-url pattern="/personal/**" access="ROLE_USER" />
<security:intercept-url pattern="/favorite/**" access="ROLE_USER" />
//需要替换的Filter顺序,配置自定义custom-filter时必须蔣auto-config="false",不然会报已经存在同样的过滤器错误
<security:custom-filter ref="myLoginFilter" position="FORM_LOGIN_FILTER" />
//登出配置
<security:logout logout-success-url="${local.service.url}"/>
</security:http>
//密码加密工具类
<bean id="encoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"/>
//认证管理器
<security:authentication-manager alias="authenticationManager">
//UserDetailsService实现 主要用于用户的查询
<security:authentication-provider user-service-ref="userLoginService">
<security:password-encoder ref="encoder">
</security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="myLoginFilter" class="com.sale114.www.sercurity.MyUsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureHandler" ref="failureHandler"/>
<property name="authenticationSuccessHandler" ref="successHandler"/>
</bean>
//成功登录后
<bean id="successHandler" class="com.sale114.www.sercurity.MySavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="${local.service.url}"/>
</bean>
//登录失败
<bean id="failureHandler" class="com.sale114.www.sercurity.MySimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="${local.service.url}/login.html?validated=false"/>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="${local.service.url}/login.html" />
</bean>
</beans>
2 UserLoginServiceImpl 查询用户实现类
@Named("userLoginService")
public class UserLoginServiceImpl implements UserDetailsService ,LoginService{
@Inject
private UserLoginDAO userLoginDAO;
@Override
public WrappedUserLogin getUserLogin() {
try {
WrappedUserLogin wrappedUserLogin = (WrappedUserLogin) SecurityContextHolder
.getContext().getAuthentication().getPrincipal();
return wrappedUserLogin;
} catch (Exception e) {
return null;
}
}
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
System.out.println("用户名-------------"+username);
UserLogin userLogin = null;
if(username != null && !"".equals(username)&& username.indexOf("@") > 0){
userLogin = userLoginDAO.findByEmail(username);
username = userLogin.getNick();
}else{
userLogin = userLoginDAO.findByNick(username);
}
System.out.println("user is null ---"+userLogin.getUserType());
String nick = userLogin.getNick();
String email = userLogin.getEmail();
String mobile = userLogin.getMobile();
int userType = userLogin.getUserType();
List<GrantedAuthority> resultAuths = new ArrayList<GrantedAuthority>();
// 前台用户
if (userType == 1) {
resultAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
} else {
resultAuths.add(new SimpleGrantedAuthority("ROLE_BACK_USER"));
}
return new WrappedUserLogin(userLogin.getId(), email, nick, mobile, userLogin.getPassword(), userType,resultAuths);
}
}
3 重写用户名密码验证
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
//用户名
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
//密码
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
//需要回调的URL 自定义参数
public static final String SPRING_SECURITY_FORM_REDERICT_KEY = "spring-security-redirect";
/**
* @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}
*/
@Deprecated
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private String redirectParameter = SPRING_SECURITY_FORM_REDERICT_KEY;
private boolean postOnly = true;
//~ Constructors ===================================================================================================
public MyUsernamePasswordAuthenticationFilter() {
super();
}
//~ Methods ========================================================================================================
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
String redirectUrl = obtainRedercitUrl(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
//自定义回调URL,若存在则放入Session
if(redirectUrl != null && !"".equals(redirectUrl)){
request.getSession().setAttribute("callCustomRediretUrl", redirectUrl);
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
/**
* Enables subclasses to override the composition of the password, such as by including additional values
* and a separator.<p>This might be used for example if a postcode/zipcode was required in addition to the
* password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The
* <code>AuthenticationDao</code> will need to generate the expected password in a corresponding manner.</p>
*
* @param request so that request attributes can be retrieved
*
* @return the password that will be presented in the <code>Authentication</code> request token to the
* <code>AuthenticationManager</code>
*/
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
/**
* Enables subclasses to override the composition of the username, such as by including additional values
* and a separator.
*
* @param request so that request attributes can be retrieved
*
* @return the username that will be presented in the <code>Authentication</code> request token to the
* <code>AuthenticationManager</code>
*/
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
protected String obtainRedercitUrl(HttpServletRequest request) {
return request.getParameter(redirectParameter);
}
/**
* Provided so that subclasses may configure what is put into the authentication request's details
* property.
*
* @param request that an authentication request is being created for
* @param authRequest the authentication request object that should have its details set
*/
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
/**
* Sets the parameter name which will be used to obtain the username from the login request.
*
* @param usernameParameter the parameter name. Defaults to "j_username".
*/
public void setUsernameParameter(String usernameParameter) {
Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
this.usernameParameter = usernameParameter;
}
/**
* Sets the parameter name which will be used to obtain the password from the login request..
*
* @param passwordParameter the parameter name. Defaults to "j_password".
*/
public void setPasswordParameter(String passwordParameter) {
Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
this.passwordParameter = passwordParameter;
}
/**
* Defines whether only HTTP POST requests will be allowed by this filter.
* If set to true, and an authentication request is received which is not a POST request, an exception will
* be raised immediately and authentication will not be attempted. The <tt>unsuccessfulAuthentication()</tt> method
* will be called as if handling a failed authentication.
* <p>
* Defaults to <tt>true</tt> but may be overridden by subclasses.
*/
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
}
4 SimpleUrlAuthenticationSuccessHandler重写
public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler{
@Value(value = "${local.service.url}")
private String LOCAL_SERVER_URL;
protected final Log logger = LogFactory.getLog(this.getClass());
private RequestCache requestCache = new HttpSessionRequestCache();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
SavedRequest savedRequest = requestCache.getRequest(request, response);
if (savedRequest == null) {
System.out.println("savedRequest is null ");
//用户判断是否要使用上次通过session里缓存的回调URL地址
int flag = 0;
//通过提交登录请求传递需要回调的URL callCustomRediretUrl
if(request.getSession().getAttribute("callCustomRediretUrl") != null && !"".equals(request.getSession().getAttribute("callCustomRediretUrl"))){
String url = String.valueOf(request.getSession().getAttribute("callCustomRediretUrl"));
//若session 存在则需要使用自定义回调的URL 而不是缓存的URL
super.setDefaultTargetUrl(url);
super.setAlwaysUseDefaultTargetUrl(true);
flag = 1;
request.getSession().setAttribute("callCustomRediretUrl", "");
}
//重设置默认URL为主页地址
if(flag == 0){
super.setDefaultTargetUrl(LOCAL_SERVER_URL);
}
super.onAuthenticationSuccess(request, response, authentication);
return;
}
//targetUrlParameter 是否存在
String targetUrlParameter = getTargetUrlParameter();
if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
requestCache.removeRequest(request, response);
super.setAlwaysUseDefaultTargetUrl(false);
super.setDefaultTargetUrl("/");
super.onAuthenticationSuccess(request, response, authentication);
return;
}
//清除属性
clearAuthenticationAttributes(request);
// Use the DefaultSavedRequest URL
String targetUrl = savedRequest.getRedirectUrl();
logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
if(targetUrl != null && "".equals(targetUrl)){
targetUrl = LOCAL_SERVER_URL;
}
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
public void setRequestCache(RequestCache requestCache) {
this.requestCache = requestCache;
}
}
5 认证失败控制类重写
/**
* <tt>AuthenticationFailureHandler</tt> which performs a redirect to the value of the {@link #setDefaultFailureUrl
* defaultFailureUrl} property when the <tt>onAuthenticationFailure</tt> method is called.
* If the property has not been set it will send a 401 response to the client, with the error message from the
* <tt>AuthenticationException</tt> which caused the failure.
* <p>
* If the {@code useForward} property is set, a {@code RequestDispatcher.forward} call will be made to
* the destination instead of a redirect.
*
* @author Luke Taylor
* @since 3.0
*/
public class MySimpleUrlAuthenticationFailureHandler implements AuthenticationFailureHandler{
protected final Log logger = LogFactory.getLog(getClass());
private String defaultFailureUrl;
private boolean forwardToDestination = false;
private boolean allowSessionCreation = true;
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Value(value = "${local.service.url}")
private String LOCAL_SERVER_URL;
public MySimpleUrlAuthenticationFailureHandler() {
}
public MySimpleUrlAuthenticationFailureHandler(String defaultFailureUrl) {
setDefaultFailureUrl(defaultFailureUrl);
}
/**
* Performs the redirect or forward to the {@code defaultFailureUrl} if set, otherwise returns a 401 error code.
* <p>
* If redirecting or forwarding, {@code saveException} will be called to cache the exception for use in
* the target view.
*/
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
//认证失败区别前后台:LOGIN URL
if(request.getParameter("spring-security-redirect") != null){
request.getSession().setAttribute("callUrlFailure", request.getParameter("spring-security-redirect"));
}
//若有loginUrl 则重定向到后台登录界面
if(request.getParameter("loginUrl") != null && !"".equals(request.getParameter("loginUrl"))){
defaultFailureUrl = LOCAL_SERVER_URL+"/backlogin.html?validated=false";
}
//defaultFailureUrl 默认的认证失败回调URL
if (defaultFailureUrl == null) {
logger.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage());
} else {
saveException(request, exception);
if (forwardToDestination) {
logger.debug("Forwarding to " + defaultFailureUrl);
request.getRequestDispatcher(defaultFailureUrl).forward(request, response);
} else {
logger.debug("Redirecting to " + defaultFailureUrl);
redirectStrategy.sendRedirect(request, response, defaultFailureUrl);
}
}
}
/**
* Caches the {@code AuthenticationException} for use in view rendering.
* <p>
* If {@code forwardToDestination} is set to true, request scope will be used, otherwise it will attempt to store
* the exception in the session. If there is no session and {@code allowSessionCreation} is {@code true} a session
* will be created. Otherwise the exception will not be stored.
*/
protected final void saveException(HttpServletRequest request, AuthenticationException exception) {
if (forwardToDestination) {
request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
} else {
HttpSession session = request.getSession(false);
if (session != null || allowSessionCreation) {
request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
}
}
}
/**
* The URL which will be used as the failure destination.
*
* @param defaultFailureUrl the failure URL, for example "/loginFailed.jsp".
*/
public void setDefaultFailureUrl(String defaultFailureUrl) {
this.defaultFailureUrl = defaultFailureUrl;
}
protected boolean isUseForward() {
return forwardToDestination;
}
/**
* If set to <tt>true</tt>, performs a forward to the failure destination URL instead of a redirect. Defaults to
* <tt>false</tt>.
*/
public void setUseForward(boolean forwardToDestination) {
this.forwardToDestination = forwardToDestination;
}
/**
* Allows overriding of the behaviour when redirecting to a target URL.
*/
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
protected RedirectStrategy getRedirectStrategy() {
return redirectStrategy;
}
protected boolean isAllowSessionCreation() {
return allowSessionCreation;
}
public void setAllowSessionCreation(boolean allowSessionCreation) {
this.allowSessionCreation = allowSessionCreation;
}
}
6 登录Controller和页面省略
发表评论
-
Spring Quartz定时器
2014-08-18 18:32 394Spring Quartz定时器 分类: Java 2011- ... -
SpringEL详解及应用
2013-09-22 15:14 1050SpringEL详解及应用 博客分类: Sprin ... -
使用SPRING中的线程池ThreadPoolTaskExecutor实现JAVA并发
2013-09-01 21:48 1916使用SPRING中的线程池ThreadPoolTaskE ... -
ThreadPoolTaskExecutor的配置解释
2013-09-01 21:40 827ThreadPoolTaskExecutor的配 ... -
spring xercesImpl xml 解析问题
2013-07-25 21:12 1204spring xercesImpl xml 解析问题 ...
相关推荐
使用spring mvc 和spring security 完成简单的自定义登录
Spring security的完整使用范例,支持自定义密码的加密方式,以及成功,失败的处理。是一个完整可运行的工程,码云似乎还要注册。后期考虑下用码云
springboot集成spring-security,实现自定义登录认证,代码亲测,同时附带jwt+security集成的代码,亲测可用
在项目中我们肯定不能使用Spring自己生成的登录页面,而要用我们自己的登录页面,下面通过本文给大家分享spring security自定义登录页面的实现方法,一起看看吧
在本篇文章里小编给大家整理了一篇关于自定义Spring Security的身份验证失败的处理方法,有需要的朋友们学习下。
spring security 4 小例子带自定义过滤器
主要介绍了SpringSecurity系列之自定义登录验证成功与失败的结果处理问题,本文通过实例给大家讲解的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
SpringSecurity 之自定义用户权限信息的存取,SpringSecurity教程,用户权限信息存取
springsecurity(用spring ibatis freemaker)实现的用户自定义的权限管理页面, 里头包括数据库脚本 和原数据 和原代码 主要参考http://blog.csdn.net/k10509806/article/details/6369131 这个人的文章做的
项目中使用到的技术包含SpringBoot、SpringSecurity&oauth2(安全资源和授权中心模式、包括登录接口自定义返回字段、自定义手机号+密码登录、自定义免密登录)、Queue队列、线程池、xss攻击配置、SpringCache、Mybatis...
NULL 博文链接:https://jiawu.iteye.com/blog/400351
springboot+ spring security实现登录认证
1.本项目为SpringCloud Gateway的微服务框架,整合了SpringSecurity,微服务间使用Redis来获取登陆的用户信息。 2.由于Gat
SpringBoot+SpringSecurity整合示例代码,实现了从数据库中获取信息进行登录认证和权限认证。 本项目为idea工程,请用idea2019导入(老版应该也可以)。 本项目用户信息所需sql文件,在工程的resources文件夹下,...
springsecuritytest自定义权限成功实例.rar 每个类都有相应的详细的介绍,看懂不难,当前前提还是需要对Springsecurity有些了解,自定义权限拦截器;认证管理器;用户详细信息;资源访问管理;用户信息查询等类;
应用中涉及到安全认证,目前项目有独立的统一认证网关,所以登录时只需要将安全认证网关的认证后信息塞到spring security中,由security3来管理用户的权限设置。目前项目由spring security2升级到spring security3。...
主要介绍了Spring Security自定义登录原理及实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
主要给大家介绍了关于spring security自定义认证登录的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
SpringSecurity4 样例工程(自定义登录页,从数据库获取用户名密码)
主要介绍了Spring security自定义用户认证流程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下