未经授权的访问被拒绝例外

时间:2016-06-02 06:46:55

标签: java rest spring-mvc spring-security

我是春天的RESTful Web服务新手,每当我通过邮递员请求URL时,我从服务器端获得随机生成的令牌,这里你是控制器代码,通过这个我得到随机生成的令牌。

  @RequestMapping(value = "/api/authenticate", method = RequestMethod.POST)
public @ResponseBody
Result doLogIn(@RequestParam("BulkData") String bulkData, HttpServletResponse response) throws Exception {

    ObjectMapper mapper = new ObjectMapper();
    JsonNode actualObj = null;
    try {
        actualObj = mapper.readTree(bulkData);
    } catch (IOException e1) {
        e1.printStackTrace();
        return new Result("Invalid Request", ResultCodes.LOGIN_FAILURE);
    }

    String userName = actualObj.get("userName").asText();
    String password = actualObj.get("password").asText();

    logger.debug("[REST]: Attempting login for -> " + userName);
    UserDetails details = userDetailService.loadUserByUsername(userName);
    // validate password
    if (details != null && !details.getPassword().equals(password)) {
        logger.debug("[REST]: Invalid username/password");
        try {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid username/password");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new Result("Invalid username or password", ResultCodes.LOGIN_FAILURE);
    }
    // Generate token. ATM, use only username
    String generatedToken = Jwts.builder().setSubject(userName)
            .setIssuedAt(new Date())
            // set token expiration time
            .setExpiration(new Date(System.currentTimeMillis() + Config.TOKEN_EXPIRY_PERIOD))
            .signWith(SignatureAlgorithm.HS256, servletContext.getInitParameter("API_SECRET_KEY"))

            .compact();
    // provide token to user in form of a Http Header
    response.addHeader(Config.AUTH_TOKEN_HEADER_NAME, generatedToken);

    return new Result("Login Success", ResultCodes.LOGIN_SUCCESS_TOKEN_GENERATED);
}

这是授权的代码,为此我正在使用AuthenticationTokenProcessingFilter,

public class AuthenticationTokenProcessingFilter extends GenericFilterBean {

@Autowired
private UserDetailService userDetailService;

@Autowired
private AuthenticationManager authenticationManager;

private static Logger logger = Logger.getLogger(AuthenticationTokenProcessingFilter.class);

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

    // Exclude login URL
    if(req.getRequestURI().endsWith("/api/authenticate")) {
        chain.doFilter(req, response);
        return;
    }

    // Client must send token in header
    String authHeader = req.getHeader(Config.AUTH_TOKEN_HEADER_NAME);
    if (authHeader == null) {
        logger.error("[REST]: Authentication header was null...");
        throw new ServletException("Missing or invalid Authorization header.");
    }

    // Parse token, fetch user and reload Security Context
    try {

        String SECRET_KEY = getServletContext().getInitParameter("API_SECRET_KEY");
        Jws<Claims> claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(authHeader);
        Claims claim = claims.getBody();
        String userName = claim.getSubject();
        logger.debug("[REST]: Token of user -> " + userName + " expires: " + claim.getExpiration());
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userName, userDetailService.loadUserByUsername(userName).getPassword());
        token.setDetails(new WebAuthenticationDetails(req));
        Authentication authentication = authenticationManager.authenticate(token);
        SecurityContextHolder.getContext().setAuthentication(authentication);
    } catch (SignatureException e) {
        logger.debug("[REST]: Invalid token");
        throw new ServletException("Invalid token.");
    }
    chain.doFilter(req, response);

    // clear security context now because we are going for Stateless Web Services
    SecurityContextHolder.getContext().setAuthentication(null);
}

现在我想使用这个生成的令牌来调用这个方法,

    @RequestMapping(value="/api/admin/getEmployeerole", method=RequestMethod.POST)
  public List<EmployeeRole> EmployeeRoleList()  {
  List<EmployeeRole> getRole=employeeRoleService.getAll();
          return getRole;         
  }

现在当我将这个URL写入邮递员并将生成的令牌添加到标题中时,我发生了什么,我使用了授权类型(No auth),我也尝试过基本的授权,我的请求仍然是customAuthenticationEntrypoint和它抛出访问被拒绝的异常,即用户角色是匿名的,在服务器端我获得状态401未经授权。如果有人可以帮助克服这一点,那将是很好的。

这里你是我的春季安全配置..

 <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:context="http://www.springframework.org/schema/context"
        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-4.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.0.xsd">


    <context:component-scan base-package="hp.bootmgr.authentication.provider" />

    <http pattern="/resources/**" security="none" />

    <http pattern="/api/**" realm="Protected API" use-expressions="true" auto-config="false" create-session="stateless" entry-point-ref="customAuthenticationEntryPoint">
<!--        <custom-filter   position="FORM_LOGIN_FILTER" /> -->
        <intercept-url pattern="/api/authenticate" access="permitAll()" />
        <intercept-url pattern="/api/admin/**" access="hasRole('ADMIN')" />
        <intercept-url pattern="/api/user/**" access="hasAnyRole('ADMIN', 'EMPLOYEE')" />
        <intercept-url pattern="/api/member/**" access="hasAnyRole('ADMIN', 'MEMBER')" />
        <!--<form-login
            login-page="/api/authenticate"
            login-processing-url="/j_spring_security_check"
            username-parameter="userName"
            password-parameter="password" />-->
        <logout logout-url="/logout"/>
        <csrf disabled="true"/>
    </http>

    <http auto-config="true" use-expressions="true" entry-point-ref="authenticationEntryPoint">
        <access-denied-handler error-page="/403" />
        <intercept-url pattern="/login" access="true"/>
        <intercept-url pattern="/admin/**" access="hasRole('ADMIN')" />
        <!-- Allow access to user pages to admin, as long as there is no more other rules-->
        <intercept-url pattern="/user/**" access="hasAnyRole('ADMIN', 'EMPLOYEE')" />
        <intercept-url pattern="/member/**" access="hasAnyRole('ADMIN', 'MEMBER')" />
        <form-login 
            login-page="/login"
            default-target-url="/home"
            authentication-failure-url="/login?failed=1"
            login-processing-url="/j_spring_security_check"
            username-parameter="userName"
            password-parameter="password" />
        <logout logout-success-url="/login?logout=1" invalidate-session="true" logout-url="/logout"/>
        <!-- enable csrf protection -->
        <csrf disabled="true"/>
        <session-management>
            <concurrency-control max-sessions="1" expired-url="/login" />
        </session-management>
    </http>    

    <beans:bean id="customAuthenticationEntryPoint" class="hp.bootmgr.web.services.authentication.CustomAuthenticationEntryPoint" />
    <beans:bean id="authenticationTokenProcessingFilter" class="hp.bootmgr.web.services.authentication.AuthenticationTokenProcessingFilter" />
    <beans:bean id="authenticationEntryPoint" class="hp.bootmgr.security.AuthenticationEntryPoint">
        <beans:constructor-arg name="loginUrl" value="/login"/>
    </beans:bean>

    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userDetailService" />
    </authentication-manager>

</beans:beans>

0 个答案:

没有答案