หน้าเว็บ

วันพุธที่ 9 มกราคม พ.ศ. 2556

การทำ Login ด้วย Spring security


1. เนื่องจากโปรเจ็คผมเป็น maven ให้ เพิ่ม dependencies ต่อไปนี้ลงไปใน pom.xml
<!-- spring -->            
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>3.1.3.RELEASE</version>
    <type>jar</type>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>3.1.3.RELEASE</version>
    <type>jar</type>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>3.1.3.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>3.1.3.RELEASE</version>
</dependency>
<!-- Spring -->



<!-- spring security -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-acl</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>3.1.2.RELEASE</version>
</dependency>
<!-- spring security -->
2. เพิ่ม file applicationContext-security.xml ไว้ใน WEB-INF
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" 
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:util="http://www.springframework.org/schema/util"
             xmlns:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans 
                 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                 http://www.springframework.org/schema/security 
                 http://www.springframework.org/schema/security/spring-security-3.1.xsd
                 http://www.springframework.org/schema/util 
                 http://www.springframework.org/schema/util/spring-util-3.0.xsd
                 http://www.springframework.org/schema/context 
                 http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <global-method-security pre-post-annotations="enabled">
    </global-method-security>

    <http  use-expressions="true" auto-config="true">
        <intercept-url pattern="/*" 
                       access="isAuthenticated()" />
        <intercept-url pattern="/editor/*" 
                               access="hasRole('EDITOR')" />
        <intercept-url pattern="/editor/admin/*" 
                                       access="hasRole('ADMIN')" />
        <logout logout-success-url="/login"/>
        <form-login login-page="/login/" 
                    default-target-url="/" 
                    always-use-default-target="true" />
        
        <remember-me key="rememberMeKey" 
                     user-service-ref="userDetailsService"/>        
    </http>
    <beans:bean id="userDetailsService" 
                class="com.blogspot.na5cent.jsflearning.services.authentication.UserDetailServices">
    </beans:bean>
    <authentication-manager alias="authenManager">
        <authentication-provider user-service-ref="userDetailsService">
        </authentication-provider>
    </authentication-manager>
    <beans:bean id="messageSource"
                class="org.springframework.context.support.ResourceBundleMessageSource">
        <beans:property name="basename" 
                        value="springsecurity"/>
    </beans:bean>
</beans:beans> 
อธิบาย code
  • <global-method-security/>  เป็นการ enable annotation @Secured คือให้สามารถใช้ annotation นี้ในการจำกัดสิทธิ์การเข้าถึง method ต่างๆ ของ class ได้
  • <intercept-url/> เป็น tag ที่กำหนดสิทธิ์การเข้าถึง ว่าแต่ละ  url จะให้เข้าถึงได้ด้วยสิทธิ์ใด
    • pattern  คือ pattern ของ url นั้น เช่น /editor/admin/* คือ url ที่ขึ้นต้นด้วย /editor/admin/
    •  access คือ การเข้าถึง url นั้น ด้วยสิทธิ์ใด
      • isAuthenticated() คือ  สิทธิ์ใดก็ได้  แต่ต้อง login เข้ามาก่อน
      •  hasRole(‘ADMIN’) คือสิทธิ์การเข้าใช้งาน url นั้นเป็น ADMIN
      •  hasRole(‘EDITOR’) คือสิทธิ์การเข้าใช้งาน url นั้นเป็น EDITOR
  • <logout/> คอนฟิก เกี่ยวกับการ logout
    • logout-success-utl  คือ เมื่อ logout success แล้วให้ไปที่ page ใด
  •  <form-login/> คอนฟิกเกี่ยวกับ form login
    •  login-page  คือ page login อยู่ที่ page ใด  ในที่นี้คือ “/login/”
    • default-target-url คือ เมื่อ login เสร็จ  จะให้ไปที่ page ใด ในที่นี้คือ “/” (root context)
    • always-use-default-target คือ ใช้  url จาก default-target-url เสมอ 
  • <remember-me/> ใช้สำหรับการจำรหัสผ่านของ web application 
    • key
    • user-service-ref คือ service ที่ใช้ในการตรวจสอบการจำการ login (ใช้ตัวเดียวกันกับตัว login)
  • <beans:bean />  เป็นการอ้างไปถึง bean นั้นๆ
    • id=”userDetailsService” คือเป็นการ identify  bean นั้นๆ
    • class=”com.blogspot….”  ระบุว่า userDetailsService  นั้น เก็บไว้ที่ใด  หรือใช้  Class ใดเป็น service login
  • <authentication-manager/>  เป็นส่วน config service login
    • <authentication-provider/> เป็นการกำหนด login service
      • user-service-ref คือ  ให้อ้างไปที่ service ใด (ใช้ service ใดในการ login)
  • <beans:bean/> เป็นการอ้างไปถึง bean นั้นๆ
    • id=”messageSource”  คือเป็นการ identify  bean นั้นๆ  (ในที่นี้คือการ config พวก error message  โดยเราจะให้ class ResourceBundleMessageSource  เป็นตัวจัดการ error message ที่เกิดจากการ login  เช่น login ไม่ผ่าน username password ไม่ถูกต้อง, user ถูก disabled ไว้เป็นต้น)
    • class=”org.springframwork…” 

3. สร้าง service สำหรับ authentication provider  หรือ service ที่ใช้สำหรับการ login (authentication)
ในที่นี้เราจะ implements UserDetailsService  ซึ่งจะมี method loadUserByUsername ที่เราต้อง implement มันเอง  spring จะส่ง username มาให้  จากนั้นเราอาจจะใช้ username นั้นไป find user ใน database (ใช้แค่ username)  แล้ว return เป็น oject  UserDetails  หลังจากนั้น  spring จะไปตรวจสอบ password ให้เราเอง  เพื่อป้องกันการโจมตีจาก SQL injection  
package com.blogspot.na5cent.jsflearning.services.authentication;

import com.blogspot.na5cent.jsflearning.model.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

/**
 *
 * @author Redcrow
 */
public class UserDetailServices implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = new User();
        System.out.println("try login by user name => " + username);
        if (!"admin".equals(username) && !"editor".equals(username) && !"public".equals(username)) {
            throw new UsernameNotFoundException("login incorrect");
        }else{
            user.setUsername(username);
            user.setPassword("1234");
        }
        return new UserDetaislApp(user);
    }
}

4. สร้าง class user details  (สำหรับการตรวจสอบสิทธิ์ หรือ authorization)
package com.blogspot.na5cent.jsflearning.services.authentication;

import com.blogspot.na5cent.jsflearning.model.User;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

/**
 *
 * @author Redcrow
 */
public class UserDetaislApp implements UserDetails {

    public static final GrantedAuthority ADMIN_ROLE = new SimpleGrantedAuthority("ADMIN");
    public static final GrantedAuthority EDITOR_ROLE = new SimpleGrantedAuthority("EDITOR");
    public static final GrantedAuthority PUBLIC_ROLE = new SimpleGrantedAuthority("PUBLIC");
    private User user;
    private Set<GrantedAuthority> grants;

    
    public UserDetaislApp(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if (grants == null) {
            grants = new HashSet<GrantedAuthority>();
            switch (user.getUsername()) {
                case "admin":
                    grants.add(PUBLIC_ROLE);
                    grants.add(EDITOR_ROLE);
                    grants.add(ADMIN_ROLE);
                    break;
                case "editor":
                    grants.add(PUBLIC_ROLE);
                    grants.add(EDITOR_ROLE);
                    break;
                default:
                    grants.add(PUBLIC_ROLE);
                    break;
            }
        }
        return grants;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}


  • บรรทัดที่ 17- 19 GrantedAuthority คือ  class ที่ใช้สำหรับระบุสิทธิ์ การเข้าถึง  ซึ่งในที่นี้เราจะระบุกี่สิทธิ์ก็ได้
  • บรรทัดที่ 29  method getAuthorities()  เป็น method ที่ใช้สำหรับกำหนดสิทธิ์  ว่าเราจะให้ user ใด  มีสิทธิ์ใดได้บ้าง  ซึ่ง spring framework จะมาอ่านไปเอง


5. ที่ web.xml ให้เพิ่ม config ต่อไปนี้ลงไป
...
...
...
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext*.xml</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- security -->
    <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>/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener>
    <!-- security -->
...
...
...

  • บรรทัดที่  4-7 <context-param/เป็นการกำหนดตัวแปร ให้ contextConfigLocation   อ้างไปที่ /WEB-INF/applicationContext*.xml  หมายถึง  config ของ spring  จะเป็น file ที่ขึ้นต้นด้วย  applicationContext  ซึ่ง spring framework จะมาอ่านค่าตัวแปรนี้ตอน start application  เพื่อนำ file config ต่างๆ  ไปดำเนินการ
  • บรรทัดที่  9-11 <listener/> เป็นการสร้าง listener เพื่อคอยดักฟังเหตุการณ์บางอย่างที่อาจจะเกิดขึ้น  ซึ่งในที่นี้เป็น servlet context list  ที่เอาไว้ listener ตอน application start และ application destroy เพื่อให้ spring ทำการกำหนดค่า  และเคลียร์ค่าข้อมูลบางอย่าง
  • บรรทัดที่ 14-21<filter/> เป็น filter ที่เอาไว้กรอง request  response จาก client  เพื่อตรวจสอบการ login และสิทธิ์การเข้าถึงในแต่ละ request <filter-mapping/>  ให้ filter ที่ url  ใดบ้าง  ซึ่งในที่นี้คือ ทุกๆ url

6. เขียน html file หน้า login
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui" 
      xml:lang="en" 
      lang="en">
    <h:head>
        <title>login page</title>
    </h:head>
    <h:body>
        <form name='f' 
              action='#{facesContext.externalContext.requestContextPath}/j_spring_security_check' 
              method='POST'>
            <table>
                <tr>
                    <td>
                        username : 
                    </td>
                    <td>
                        <input name="j_username"/>
                    </td>
                </tr>
                <tr>
                    <td>
                        password : 
                    </td>
                    <td>
                        <input name="j_password" type="password"/>
                    </td>
                </tr>
                <tr>
                    <td>
                        remember me : 
                    </td>
                    <td>
                        <input type='checkbox' name='_spring_security_remember_me'/>
                    </td>
                </tr>
                <tr>
                    <td>

                    </td>
                    <td>
                        <button type="sybmit">login</button>
                    </td>
                </tr>
            </table>
        </form>
    </h:body>
</html>
  • บรรทัดที่ 12 <form/> เป็น form สำหรับการ login  โดยมี method เป็น POST และให้ action ไปที่  “/context root/j_spring_security_check”

public page : contextRoot/index.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>public</title>
    </head>
    <body>
        <b>public page</b><br/>
        <a href="editor/">Editor</a><br/>
        <a href="editor/admin/">Admin</a>
        <br/>
        <br/>
        <a href="#{facesContext.externalContext.requestContextPath}/j_spring_security_logout">logout</a>
    </body>
</html>

การ logout เราจะให้ link ชี้ไปที่ j_spring_security_logout


 ทดสอบเข้าใช้งานด้วย username : admin 





User admin สามารถเข้าใช้งานได้ทุกหน้า  เพราะว่าถ้า user name  == “admin”  ให้มี authority ทุก role




 ทดสอบเข้าใช้งานด้วย username : editor 








สังเกตว่า user editor ไม่สามารถเข้าใช้งาน page ที่เป็น /editor/admin/ ได้  เพราะ page นี้อนุณาตเฉพาะสิทธิ์ admin เท่านั้น




 ทดสอบเข้าใช้งานด้วย  username : public 





        User public เข้าได้แต่ หน้าที่เป็น public เท่านั้น        

        โค๊ดสำหรับไม่ให้ browser cache page html ไว้  ใช้ในกรณีที่เรา logout  แล้ว  มันสามารถ back กลับมายังหน้าเดิมได้

CacheControlFilter.java
package com.blogspot.na5cent.jsflearning.filters;

import java.io.IOException;
import java.util.Date;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author Redcrow
 */
@WebFilter(urlPatterns="/*", filterName="cacheControlFilter")
public class CacheControlFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setHeader("Expires", new Date().toString());
        resp.setHeader("Last-Modified", new Date().toString());
        resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
        resp.setHeader("Pragma", "no-cache");

        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }
}
การดึงข้อมูล user ที่ login มาใช้งาน
Logins.java
package com.blogspot.na5cent.jsflearning.services.authentication;

import org.springframework.security.core.Authentication;
import com.blogspot.na5cent.jsflearning.model.User;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

/**
 *
 * @author Redcrow
 */
public class Logins {
    
    public static User getUser() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authen = securityContext.getAuthentication();
        User user = null;
        if (authen != null) {
            Object principal = authen.getPrincipal();
            if (pricipal instanceof UserDetailsApp) {
                user = ((UserDetailsApp) principal).getUser();
            } else if (principal instanceof String) {
                user = new User();
                user.setUsername("anonymous");
            }       
        }

        return user;
    }
}

เรียกใช้งาน
SessionMB.java
package com.blogspot.na5cent.jsflearning.managedbean;

import com.blogspot.na5cent.jsflearning.model.User;
import com.blogspot.na5cent.jsflearning.services.authentication.Logins;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

/**
 *
 * @author Redcrow
 */
@ManagedBean
@SessionScoped
public class SessionMB {

    private User user;

    @PostConstruct
    public void postContruct() {
        user = Logins.getUser();
    }

    public User getUser() {
        if(user == null){
            user = new User();
        }
        return user;
    }
}

ทดสอบ
หน้าแรกที่ login เข้ามาน่ะครับ
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>public</title>
    </head>
    <body>
        user [ #{sessionMB.user.username} : #{sessionMB.user.password} ]
        <br/>
        <b>public page</b><br/>
        <a href="editor/">Editor</a><br/>
        <a href="editor/admin/">Admin</a>
        <br/>
        <br/>
        <a href="#{facesContext.externalContext.requestContextPath}/j_spring_security_logout">logout</a>
    </body>
</html>

การแสดงข้อผิดพลาดจากการ Login
        ให้นำ file springsecurity.properties ซึ่งเป็น file ที่ใช้สำหรับการเก็บ message error ต่างๆ  ไปเก็บไว้ที่ class path


springsecurity.properties
AuthByAdapterProvider.incorrectKey=The presented AuthByAdapter implementation does not contain the expected key
BasicAclEntryAfterInvocationProvider.noPermission=Authentication {0} has NO permissions at all to the domain object {1}
BasicAclEntryAfterInvocationProvider.insufficientPermission=Authentication {0} has ACL permissions to the domain object, but not the required ACL permission to the domain object {1}
ConcurrentSessionControllerImpl.exceededAllowed=Maximum sessions of {0} for this principal exceeded
ProviderManager.providerNotFound=No AuthenticationProvider found for {0}
AnonymousAuthenticationProvider.incorrectKey=The presented AnonymousAuthenticationToken does not contain the expected key
CasAuthenticationProvider.incorrectKey=The presented CasAuthenticationToken does not contain the expected key
CasAuthenticationProvider.noServiceTicket=Failed to provide a CAS service ticket to validate
NamedCasProxyDecider.untrusted=Nearest proxy {0} is untrusted
RejectProxyTickets.reject=Proxy tickets are rejected
AbstractSecurityInterceptor.authenticationNotFound=An Authentication object was not found in the SecurityContext
AbstractUserDetailsAuthenticationProvider.onlySupports=Only UsernamePasswordAuthenticationToken is supported
AbstractUserDetailsAuthenticationProvider.locked=รหัสผู้ใช้งานนี้ถูกล็อก 
AbstractUserDetailsAuthenticationProvider.disabled=รหัสผู้ใช้งานนี้ถูกระงับการใช้งาน 
AbstractUserDetailsAuthenticationProvider.expired=รหัสผู้ใช้งานนี้หมดอายุ 
AbstractUserDetailsAuthenticationProvider.credentialsExpired=รหัสผู้ใช้งานนี้หมดอายุ 
AbstractUserDetailsAuthenticationProvider.badCredentials=รหัสผู้ใช้งาน/รหัสผ่าน ไม่ถูกต้อง  
X509AuthenticationProvider.certificateNull=Certificate is null
DaoX509AuthoritiesPopulator.noMatching=No matching pattern was found in subjectDN: {0}
RememberMeAuthenticationProvider.incorrectKey=The presented RememberMeAuthenticationToken does not contain the expected key
RunAsImplAuthenticationProvider.incorrectKey=The presented RunAsUserToken does not contain the expected key
DigestProcessingFilter.missingMandatory=Missing mandatory digest value; received header {0}
DigestProcessingFilter.missingAuth=Missing mandatory digest value for 'auth' QOP; received header {0}
DigestProcessingFilter.incorrectRealm=Response realm name {0} does not match system realm name of {1}
DigestProcessingFilter.nonceExpired=Nonce has expired/timed out
DigestProcessingFilter.nonceEncoding=Nonce is not encoded in Base64; received nonce {0}
DigestProcessingFilter.nonceNotTwoTokens=Nonce should have yielded two tokens but was {0}
DigestProcessingFilter.nonceNotNumeric=Nonce token should have yielded a numeric first token, but was {0}
DigestProcessingFilter.nonceCompromised=Nonce token compromised {0}
DigestProcessingFilter.usernameNotFound=Username {0} not found
DigestProcessingFilter.incorrectResponse=Incorrect response
JdbcDaoImpl.notFound=User {0} not found
JdbcDaoImpl.noAuthority=User {0} has no GrantedAuthority
SwitchUserProcessingFilter.noCurrentUser=No current user associated with this request
SwitchUserProcessingFilter.noOriginalAuthentication=Could not find original Authentication object
SwitchUserProcessingFilter.usernameNotFound=Username {0} not found
SwitchUserProcessingFilter.locked=รหัสผู้ใช้งานนี้ถูกล็อก 
SwitchUserProcessingFilter.disabled=รหัสผู้ใช้งานนี้ถูกระงับการใช้งาน 
SwitchUserProcessingFilter.expired=รหัสผู้ใช้งานนี้หมดอายุ 
SwitchUserProcessingFilter.credentialsExpired=รหัสผู้ใช้งานนี้หมดอายุ 
AbstractAccessDecisionManager.accessDenied=Access is denied
LdapAuthenticationProvider.emptyUsername=Empty username not allowed
LdapAuthenticationProvider.emptyPassword=รหัสผู้ใช้งาน/รหัสผ่าน ไม่ถูกต้อง 
DefaultIntitalDirContextFactory.communicationFailure=Unable to connect to LDAP server
DefaultIntitalDirContextFactory.badCredentials=รหัสผู้ใช้งาน/รหัสผ่าน ไม่ถูกต้อง 
DefaultIntitalDirContextFactory.unexpectedException=Failed to obtain InitialDirContext due to unexpected exception
PasswordComparisonAuthenticator.badCredentials=รหัสผู้ใช้งาน/รหัสผ่าน ไม่ถูกต้อง 
BindAuthenticator.badCredentials=รหัสผู้ใช้งาน/รหัสผ่าน ไม่ถูกต้อง 
BindAuthenticator.failedToLoadAttributes=รหัสผู้ใช้งาน/รหัสผ่าน ไม่ถูกต้อง 
UserDetailsService.locked=รหัสผู้ใช้งานนี้ถูกล็อก 
UserDetailsService.disabled=รหัสผู้ใช้งานนี้ถูกระงับการใช้งาน 
UserDetailsService.expired=รหัสผู้ใช้งานนี้หมดอายุ 
UserDetailsService.credentialsExpired=รหัสผู้ใช้งานนี้หมดอายุ 
ที่หน้า login ให้เพิ่มต่อไปนี้ลงไป
...
...
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
...
..
เวลาที่ login ไม่ได้ มันก็จะขึ้นแบบนี้


ใช้ isUserInRole ในการตรวจสอบสิทธิ์
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui" >
    <h:head>
        <title>public</title>
    </h:head>
    <h:body>
        user [ #{sessionMB.user.username} : #{sessionMB.user.password} ]
        <br/>
        <b>public page</b><br/>
        <a href="editor/">Editor</a><br/>
        <a href="editor/admin/">Admin</a>
        <br/>
        <br/>
        <p:commandButton value="admin" 
                         type="button"
                         rendered="#{facesContext.externalContext.isUserInRole('ADMIN')}"/>
        <p:spacer width="5"/>
        <p:commandButton value="editor" 
                         type="button"
                         rendered="#{facesContext.externalContext.isUserInRole('EDITOR')}"/>
        <p:spacer width="5"/>
        <p:commandButton value="public" 
                         type="button"
                         rendered="#{facesContext.externalContext.isUserInRole('PUBLIC')}"/>
        <br/>
        <br/>
        <a href="#{facesContext.externalContext.requestContextPath}/j_spring_security_logout">logout</a>
    </h:body>
</html>

 ทดสอบเข้าใช้งานด้วย user public 



 ทดสอบเข้าใช้งานด้วย user editor 



 ทดสอบเข้าใช้งานด้วย user admin 


การตรวจสอบว่า user login รึยัง  เราจะใช้
<h:outputLink value="#{facesContext.externalContext.requestContextPath}/login.xhtml"
              rendered="#{empty facesContext.externalContext.userPrincipal.name}">
    <h:outputText value="เข้าสู่ระบบ"  styleClass="blue-text"/>
</h:outputLink>
<h:outputLink value="#{facesContext.externalContext.requestContextPath}/login.xhtml"
              rendered="#{not empty facesContext.externalContext.userPrincipal.name}">
    <h:outputText value="ออกจากระบบ"  styleClass="blue-text"/>
</h:outputLink>

ถ้า user login แล้ว   facesContext.externalContext.userPrincipal.name  จะไม่เป็นค่าว่าง
แต่ถ้ายังไม่ได้ login  facesContext.externalContext.userPrincipal.name  จะเป็นค่าว่างครับ

หวังว่าบทความที่ผมเขียนจะพอเป็นประโยชน์สำหรับคนอื่นได้บ้างน่ะครับ ^____^

5 ความคิดเห็น:

  1. ไม่ระบุชื่อ17 เมษายน 2557 เวลา 18:56

    ขอบคุณมากครับ สำหรับบทความนี้ครับ ^_^

    ตอบลบ
  2. ขอบคุณครับ สำหรับความรู้
    ผมขอไฟร์มาเป็นตัวอย่างหน่อยนะครับ

    ตอบลบ
    คำตอบ
    1. ลองดูใน project นี้น่ะครับ https://github.com/jittagornp/income

      ลบ
  3. สุดยอดครับ อยากสอบถามติดต่อทางไหนครับ

    ตอบลบ