您的位置:首页 > 编程语言 > Java开发

Spring Security 入门(3-11)Spring Security 的使用-自定义登录验证和回调地址

2017-06-15 17:01 627 查看
配置文件 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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐