while processing injection of spring security to my web app i get problem HTTP Status 404 error. When i try to get access for my pages first of all i get login page which is auto config, after typing login and password which is correct i get HTTP Status 404 error. Code below
web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.xml, /WEB-INF/application-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>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
application-security.xml
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.1.xsd">
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/main/**" access="hasRole('ROLE_USER')" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="adminpassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="user" password="userpassword" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
Controller
#Controller
#RequestMapping(value = "/main")
public class MainController {
#Autowired
DeputesAppealService deputesAppealService;
#Autowired
DeputesAppealDao deputesAppealDao;
#RequestMapping(value = "/mainFrame", method = RequestMethod.GET)
public String getMainPage(){
return "mainPage";
}
#RequestMapping(value = "/resultOfSearching", method = RequestMethod.GET)
public String getSearchResult(Model model, #ModelAttribute("searchChar")String searchResult) {
List<DeputesAppeal> deputesAppeals = deputesAppealService.abstractSearch(searchResult);
model.addAttribute("ListOfAppeals", deputesAppeals);
return "searchingResultPage";
}
#RequestMapping(value = "/new", method = RequestMethod.GET)
public String getAddNewAppealPage(){
return "addPage";
}
#RequestMapping(value = "/new", method = RequestMethod.POST)
public String addNewAppeal(#ModelAttribute("Appeal")DeputesAppeal deputesAppeal) {
deputesAppealService.add(deputesAppeal);
return "mainPage";
}
#RequestMapping(value = "/deleted", method = RequestMethod.GET)
public String deleteAppeal(#RequestParam(value = "id", required = true) Long id, Model model){
deputesAppealService.delete(id);
model.addAttribute("id", id);
return "deletedPage";
}
#RequestMapping(value = "/editPage", method = RequestMethod.GET)
public String GetEdit(#RequestParam(value = "id", required = true) Long id, Model model){
model.addAttribute("editedAppeal", deputesAppealService.getById(id));
return "editPage";
}
#RequestMapping(value = "/editPage", method = RequestMethod.POST)
public String editCurrentAppeal(#ModelAttribute("userAttribute") DeputesAppeal deputesAppeal,
#RequestParam(value = "id", required = true)Integer id, Model model) {
deputesAppeal.setNumber(id);
deputesAppealService.edit(deputesAppeal);
model.addAttribute("id", id);
return "editedPage";
}
}
Just see if you have springSecurityFilterChain defined in your web.xml
<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>
You also need to change Login URL as well
<c:url value="/j_spring_security_check" var="loginUrl" />
and use this in your form action:
<form action="${loginUrl}" method="post">
Related
I'm new in java development and I am trying to implement spring security on method level using #secured annotation.
When i call my "/login" I'm getting the following error:
"An Authentication object was not found in the SecurityContext"
PS:I am not using a .jsp file for login , any idea how to manage this error?
this is my code sections.
#Controller
#RequestMapping("/login")
public class LoginController {
#Autowired
public IUserService userService;
#RequestMapping(method = RequestMethod.GET)
public String success(ModelMap map) {
userService.addUser("ram", "con1234");
userService.deleteUser("ABC");
map.addAttribute("msg", "Done Successfully");
return "success";
}
}
public interface IUserService {
#Secured ({"ROLE_USER", "ROLE_ADMIN"})
public void addUser(String name, String pwd);
#Secured("ROLE_ADMIN")
public void deleteUser(String name);
}
#Repository
public class UserServiceSec implements IUserService {
#Override
public void addUser(String name, String pwd) {
System.out.println("user added");
}
#Override
public void deleteUser(String name) {
System.out.println("user deleted");
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>EQUADIS</display-name>
<welcome-file-list>
<welcome-file>/login</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet- class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-config.xml
/WEB-INF/security-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
security-config.xml
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans- 3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http auto-config="true">
<intercept-url pattern="/login" access="ROLE_USER,ROLE_ADMIN" />
<logout logout-success-url="/login" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="ram" password="con1234" authorities="ROLE_ADMIN" />
<user name="rahim" password="con1234" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
<global-method-security secured-annotations="enabled" />
<beans:bean name="userServiceSec" class="package.service.UserServiceSec"/>
You don't seem to have a DelegatingFilterProxy filter in your web.xml. You need to have the following;
<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>
I am developing application using Spring and I need to initialize Ticket object in session and then get it from another controller.
I have two controllers, so there are two xml contexts.
web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Web MVC Application</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/rest-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>index</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/index-context.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>index</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
rest-context.xml
<beans ...>
<mvc:annotation-driven/>
<context:annotation-config/>
<context:component-scan base-package="menu.MenuController"/>
</beans>
index-context.xml
<beans ...>
<mvc:annotation-driven/>
<mvc:resources mapping="/**" location="/"/>
<context:annotation-config/>
<bean class="auth.IndexWebController" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
</beans>
In the spring-context I have my Ticket bean:
<bean id="tickerProvider" class="TicketProviderImpl" scope="session">
<aop:scoped-proxy/>
together with the other beans.
This are what my controllers look like:
IndexWebController.java
#Controller
#SessionAttributes("user")
public class IndexWebController {
private static Logger logger = LoggerFactory.getLogger(IndexWebController.class);
#Autowired
private TicketProviderImpl ticketProvider;
#ModelAttribute("user")
public User populateUser() {
return new User();
}
#RequestMapping(value = "/", method = {RequestMethod.POST, RequestMethod.GET})
public ModelAndView printIndex(#ModelAttribute("user") User user,
#RequestParam(value = "iv-user", required = false) String login,
#RequestParam(value = "iv-groups", required = false) String groups) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index.html");
<...>
ticketProvider.setLogin(login);
logger.info("Пользователь установлен в " + login);
<...>
MenuController.java
#Controller
public class MenuController {
#Autowired
private TicketProviderImpl ticketProvider;
#ResponseBody
#RequestMapping("/getMenuList")
public MenuListDTO getMenuList(
#RequestParam(value = "menuId", required = true, defaultValue = "-1") long menuId,
#RequestParam(value = "parentId", required = true, defaultValue = "0") long parentId) {
<...>
System.out.println(ticketProvider.getLogin());
<...>
}
}
The problem is that when I autowire ticketProvider bean in the MenuController I get a new instance of it, not those that has been initialized in the IndexWebController. Actually I get null, but waiting for the login.
Where is the mistake or some misunderstanding of using session scoped beans?
According to this you will need another listener to expose your session to the application.
Hence adding <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> should do the trick.
I'm working with Java, Jetty and Jersey 2.18 (latest for now) hosted on a Google App Engine.
Let say I have a service such that
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/{userId}")
public Response getUser(#PathParam("userId") String userId)
{
...
}
When I do:
return Response.ok()
.entity(user)
.build();
I correctly receive an application/json content-type and body.
But when I do:
return Response
.status(404)
.entity(new ResponseModel(100, "user not found"))
.build();
same as for returning any 4XX or 5XX status, I receive a text/html content-type along with this HTML body:
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>404 Not Found</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Not Found</h1>
</body>
</html>
and not the object I put in .entity()
Edit: Here is my web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app
version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.mypackage.services;org.codehaus.jackson.jaxrs</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
org.glassfish.jersey.server.gae.GaeFeature;
org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
org.glassfish.jersey.media.multipart.MultiPartFeature;
</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.feature.Trace</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/rest/*</url-pattytern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>home.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>ObjectifyFilter</filter-name>
<filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ObjectifyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring Security Filter -->
<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>
<filter>
<filter-name>GlobalResponseFilter</filter-name>
<filter-class>com.mypackage.GlobalResponseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GlobalResponseFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
<security-constraint>
<web-resource-collection>
<web-resource-name>everything</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!-- ** -->
<!-- ** General session timeout in minutes -->
<!-- ** -->
<session-config>
<session-timeout>1440</session-timeout>
</session-config>
</web-app>
ResponseModel is just a basic serializable java class :
import java.io.Serializable;
public class ResponseModel implements Serializable
{
private static final long serialVersionUID = 1L;
private int code;
private Serializable data;
public ResponseModel()
{
}
public ResponseModel(int code, Serializable data)
{
System.err.println("Code " + code + " : " + data);
this.code = code;
this.data = data;
}
public int getCode()
{
return code;
}
public void setCode(int code)
{
this.code = code;
}
public Serializable getData()
{
return data;
}
public void setData(Serializable data)
{
this.data = data;
}
}
Can you try again with the following configuration:
<servlet>
<servlet-name>API</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
...
<init-param>
<param-name>jersey.config.server.response.setStatusOverSendError</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
This flag defines if Jersey - when sending a 4xx or 5xx response status - uses ServletResponse.sendError(flag is false) or ServletResponse.setStatus (flag is true).
Calling ServletResponse.sendError usually resets the response entity and headers and returns a (text/html) error page for the status code.
Since you want to return an own custom error entity, you need to set this flag to true.
I am trying out Spring security and I annotated some methods of my RestController with #PreAuthorize.
However, I can access all of them without being authenticated.
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Security configuration, imported by root-context:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans ...>
<global-method-security pre-post-annotations="enabled" />
<http auto-config="true">
<intercept-url pattern="/service/public/**" />
<intercept-url pattern="/service/user/**" access="ROLE_USER,ROLE_ADMIN" />
<intercept-url pattern="/service/admin/**" access="ROLE_ADMIN" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider> <user-service> <user name="admin" password="admin"
authorities="ROLE_ADMIN" /> <user name="user" password="user" authorities="ROLE_USER"
/> </user-service> </authentication-provider>
</authentication-manager>
</beans:beans>
My service:
#RestController
#RequestMapping("/service")
public class Service {
#RequestMapping(value = "/public/{name}", method = RequestMethod.GET)
public String storeEntityPublic(#PathVariable String name) {
String result = "Hello " + name + ", I am saving on the db. (PUBLIC)";
return result;
}
#PreAuthorize("hasAnyRole('ROLE_USER','ROLE_ADMIN')")
#RequestMapping(value = "/user/{name}", method = RequestMethod.GET)
public String storeEntityUserOrAdmin(#PathVariable String name) {
String result = "Hello " + name
+ ", I am saving on the db. (USER OR ADMIN)";
return result;
}
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(value = "/admin/{name}", method = RequestMethod.GET)
public String storeEntityAdmin(#PathVariable String name) {
String result = "Hello Admin " + name
+ ", I am saving on the db. (ADMIN ONLY)";
return result;
}
}
What's wrong with it?
I am using spring security, and I can't seem to see if a user has successfully logged in to save my life and then get the actual user name. The 'spring' (SecurityContextHolder) and 'J2EE' (request.getUserPrincipal()) way both return nulls.
My web.xml
<filter>
<filter-name>AuthFilter</filter-name>
<filter-class>com.company.security.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
....
<servlet>
<servlet-name>agent-desktop</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>agent-desktop</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Spring config:
<mvc:resources mapping="/r/**" location="/resources/" />
Spring security config:
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<http auto-config="true">
<intercept-url pattern="/agent/**" access="ROLE_USER" />
<intercept-url pattern="/supervisor/**" access="ROLE_USER" />
<form-login login-page="/r/views/login.html" default-target-url="/dashboard" authentication-failure-url="/r/views/loginfailed.html" />
<logout logout-success-url="/logout" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="pw123" authorities="ROLE_USER, ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Here is my filter code:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if(auth != null)
{
String name = auth.getName(); //get logged in username
System.out.println("name:"+name);
User user = (User)auth.getPrincipal();
if(user != null)
System.out.println("user:"+user.getUsername());
}
if(req.getUserPrincipal() != null) // someone has logged in - IT IS ALWAYS NULL
{
/// IT NEVER GETS IN HERE!!!!!!!!!!
I suspect you have missed out including a filter in your web.xml. You might want to read up on how to configure spring security from here
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
Use this code in web.xml instead of the filter.
<!-- Spring 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>
To get the login user details have a separate class like this
public class AccountUtils {
public static Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
public static UserAccount getLoginUserAccount() {
if (getAuthentication() != null && getAuthentication().getPrincipal() instanceof UserAccount) {
return (UserAccount)getAuthentication().getPrincipal();
}
return null;
}
public static String getLoginUserId() {
UserAccount account = getLoginUserAccount();
return (account == null) ? null : account.getUserId();
}
private AccountUtils() {}
}