OAuth认证机制入门篇

栏目: Java · 发布时间: 7年前

什么是PAC4J?

pac4j是一个简单而强大的安全引擎,用于 Java 对用户进行身份验证、获取其配置文件和管理授权,以确保web应用程序安全。它提供了一套完整的概念和组件。它基于Java 8,并在Apache 2许可下使用。它可用于大多数框架/工具和支持大多数认证/授权机制。

已经集成可用的场景

J2E • Spring Web MVC (Spring Boot) • Spring Security (Spring Boot) • Apache Shiro

Play 2.x • Vertx • Spark Java • Ratpack • Undertow

CAS server • JAX-RS • Dropwizard • Apache Knox • Jooby

身份验证机制

OAuth (Facebook, Twitter, Google…) – SAML – CAS – OpenID Connect – HTTP – OpenID – Google App Engine – Kerberos (SPNEGO/Negotiate)

LDAP – SQL – JWT – MongoDB – CouchDB – IP address – REST API

授权机制

Roles/permissions – Anonymous/remember-me/(fully) authenticated – Profile type, attribute

CORS – CSRF – Security headers – IP address, HTTP method

pac4j是一个支持多种支持多种协议的身份认证的Java客户端。

2,pac4j的12种客户端认证机制:目前我只有用过第一和第八种。

  1. OAuth  (1.0 & 2.0): Facebook, Twitter, Google, Yahoo, LinkedIn, Github… using the  pac4j-oauth  module
  2. CAS  (1.0, 2.0, SAML, logout & proxy) + REST API support using the  pac4j-cas  module
  3. HTTP  (form, basic auth, IP, header, GET/POST parameter authentications) using the  pac4j-http  module
  4. OpenID  using the  pac4j-openid  module
  5. SAML  (2.0) using the  pac4j-saml  module
  6. Google App Engine  UserService using the  pac4j-gae  module
  7. OpenID Connect  1.0 using the  pac4j-oidc  module
  8. JWT  using the  pac4j-jwt  module
  9. LDAP  using the  pac4j-ldap  module
  10. relational DB  using the  pac4j-sql  module
  11. MongoDB  using the  pac4j-mongo  module
  12. Stormpath  using the  pac4j-stormpath  module.

OAuth认证机制入门篇

3,maven配置


 1             <dependency>
 2                 <groupId>org.pac4j</groupId>
 3                 <artifactId>spring-security-pac4j</artifactId>
 4                 <version>1.4.3</version>
 5             </dependency>
 6             <dependency>
 7                 <groupId>org.pac4j</groupId>
 8                 <artifactId>pac4j-oauth</artifactId>
 9                 <version>1.8.8</version>
10             </dependency>

View Code

主要是三个jar包:

OAuth认证机制入门篇

pac4j是一个简单而强大的安全引擎,用于Java对用户进行身份验证、获取其配置文件和管理授权,以确保web应用程序安全。它提供了一套完整的概念和组件。它基于Java 8,并在Apache 2许可下使用。它可用于大多数框架/工具和支持大多数认证/授权机制。

已经集成可用的场景

  • J2E • Spring Web MVC (Spring Boot) • Spring Security (Spring Boot) • Apache Shiro
  • Play 2.x • Vertx • Spark Java • Ratpack • Undertow
  • CAS server • JAX-RS • Dropwizard • Apache Knox • Jooby

身份验证机制

  • OAuth (Facebook, Twitter, Google…) – SAML – CAS – OpenID Connect – HTTP – OpenID – Google App Engine – Kerberos (SPNEGO/Negotiate)
  • LDAP – SQL – JWT – MongoDB – CouchDB – IP address – REST API

授权机制

  • Roles/permissions – Anonymous/remember-me/(fully) authenticated – Profile type, attribute
  • CORS – CSRF – Security headers – IP address, HTTP method

项目地址: https://github.com/pac4j/pac4j/tree/pac4j-3.1.0

———————-

pom.xml

<?xml version=”1.0″ encoding=”UTF-8″?>

<project xmlns=”http://maven.apache.org/POM/4.0.0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>

<modelVersion>4.0.0</modelVersion>

<groupId>org.ikane</groupId>

<artifactId>demo</artifactId>

<version>0.0.1-SNAPSHOT</version>

<packaging>jar</packaging>

<name>spring-boot-pac4j-demo</name>

<description>Spring-boot PAC4J DEMO</description>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>1.2.8.RELEASE</version>

<relativePath/> <!– lookup parent from repository –>

</parent>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<java.version>1.7</java.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-thymeleaf</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.thymeleaf.extras</groupId>

<artifactId>thymeleaf-extras-springsecurity4</artifactId>

<version>2.1.2.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-security</artifactId>

</dependency>

<dependency>

<groupId>org.pac4j</groupId>

<artifactId>spring-security-pac4j</artifactId>

<version>1.4.1</version>

<exclusions>

<exclusion>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-web</artifactId>

</exclusion>

<exclusion>

<groupId>org.springframework.security</groupId>

<artifactId>spring-security-config</artifactId>

</exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>org.pac4j</groupId>

<artifactId>pac4j-cas</artifactId>

<version>1.8.5</version>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

Pac4jConfig.java

package org.ikane;

import org.ikane.security.ClientUserDetailsService;

import org.ikane.service.AccountService;

import org.pac4j.cas.client.CasClient;

import org.pac4j.core.client.Clients;

import org.pac4j.springframework.security.authentication.ClientAuthenticationProvider;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class Pac4jConfig {

public static String CAS_LOGIN_URL = “https://casserverpac4j.herokuapp.com/login”;

@Value(“${oauth.callback.url}”)

private String oauthCallbackUrl;

@Autowired

AccountService accountService;

@Bean

CasClient casClient() {

return new CasClient(CAS_LOGIN_URL);

}

@Bean

Clients clients() {

return new Clients(oauthCallbackUrl, casClient());

}

@Bean

ClientUserDetailsService clientUserDetailsService() {

ClientUserDetailsService clientUserDetailsService = new ClientUserDetailsService();

clientUserDetailsService.setAccountService(accountService);

return clientUserDetailsService;

}

@Bean

ClientAuthenticationProvider clientProvider() {

ClientAuthenticationProvider clientAuthenticationProvider = new ClientAuthenticationProvider();

clientAuthenticationProvider.setClients(clients());

clientAuthenticationProvider.setUserDetailsService(clientUserDetailsService());

return clientAuthenticationProvider;

}

}

SecurityConfig.java

package org.ikane;

import org.pac4j.core.client.Clients;

import org.pac4j.springframework.security.authentication.ClientAuthenticationProvider;

import org.pac4j.springframework.security.web.ClientAuthenticationFilter;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;

import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.builders.WebSecurity;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy;

@Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled=true, securedEnabled=true)

public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired

ApplicationContext context;

@Autowired

Clients clients;

@Autowired

ClientAuthenticationProvider clientProvider;

@Override

public void configure(WebSecurity web) throws Exception {

web

.ignoring()

.antMatchers(

“/**/*.css”,

“/**/*.png”,

“/**/*.gif”,

“/**/*.jpg”,

“/**/*.ico”,

“/**/*.js”

);

}

@Override

protected void configure(HttpSecurity http) throws Exception {

http

.csrf().disable()

.authorizeRequests()

.and()

.formLogin()

.loginPage(“/login”)

.permitAll()

.and()

.logout()

.logoutUrl(“/logout”)

.logoutSuccessUrl(“/”)

.permitAll()

;

http.addFilterBefore(clientFilter(), UsernamePasswordAuthenticationFilter.class);

}

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

super.configure(auth);

auth.authenticationProvider(clientProvider);

}

ClientAuthenticationFilter clientFilter() {

String suffixUrl=”/*”;

ClientAuthenticationFilter clientAuthenticationFilter = new ClientAuthenticationFilter(suffixUrl);

clientAuthenticationFilter.setClients(clients);

clientAuthenticationFilter.setSessionAuthenticationStrategy(sas());

//clientAuthenticationFilter.setAuthenticationManager((AuthenticationManager)clientProvider);

return clientAuthenticationFilter;

/*

return new ClientAuthenticationFilter(

clients: clients,

sessionAuthenticationStrategy: sas(),

authenticationManager: clientProvider as AuthenticationManager

)

*/

}

@Bean

SessionAuthenticationStrategy sas() {

return new SessionFixationProtectionStrategy();

}

}

SpringBootPac4jDemoApplication.java

package org.ikane;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class SpringBootPac4jDemoApplication {

public static void main(String[] args) {

SpringApplication.run(SpringBootPac4jDemoApplication.class, args);

}

}

ThymeleafConfig.java

package org.ikane;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;

@Configuration

public class ThymeleafConfig {

@Bean

public SpringSecurityDialect springSecurityDialect() {

return new SpringSecurityDialect();

}

}

IndexController.java

package org.ikane.controller;

import org.springframework.security.access.prepost.PreAuthorize;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

class IndexController {

@RequestMapping(“/”)

@PreAuthorize(“isAuthenticated()”)

public String index() {

return “index”;

}

}

LoginController.java

package org.ikane.controller;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.pac4j.cas.client.CasClient;

import org.pac4j.core.client.BaseClient;

import org.pac4j.core.client.Clients;

import org.pac4j.core.context.J2EContext;

import org.pac4j.core.context.WebContext;

import org.pac4j.core.exception.RequiresHttpAction;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.authentication.AnonymousAuthenticationToken;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

@Controller

public class LoginController {

Logger logger = LoggerFactory.getLogger(LoginController.class);

@Autowired

private Clients clients;

@RequestMapping(“/login”)

public String login(HttpServletRequest request, HttpServletResponse response, Model model) {

if (isAuthenticated()) {

return “redirect:/”;

}

final WebContext context = new J2EContext(request, response);

//定义cas客户端

final CasClient casClient = (CasClient) clients.findClient(CasClient.class);

model.addAttribute(“casAuthUrl”, getClientLocation(casClient, context));

return “login”;

}

//获取客户端的链接

public String getClientLocation(BaseClient client, WebContext context) {

try {

return ((CasClient)client).getRedirectAction(context, false).getLocation();

} catch (RequiresHttpAction e) {

e.printStackTrace();

logger.error(“error”, e);

return null;

}

//return client.getRedirectAction(context, false, false).getLocation();

}

protected boolean isAuthenticated() {

Authentication auth = SecurityContextHolder.getContext().getAuthentication();

return !(auth instanceof AnonymousAuthenticationToken);

}

}

ClientUserDetails.java

package org.ikane.security;

import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.userdetails.UserDetails;

class ClientUserDetails implements UserDetails {

private static final long serialVersionUID = 6523314653561682296L;

String username;

String providerId;

Collection<GrantedAuthority> authorities;

String password;

public ClientUserDetails() {

// TODO Auto-generated constructor stub

}

public ClientUserDetails(String username, String providerId, Collection<GrantedAuthority> authorities) {

super();

this.username = username;

this.providerId = providerId;

this.authorities = authorities;

}

@Override

public Collection<? extends GrantedAuthority> getAuthorities() {

return authorities;

}

@Override

public String getPassword() {

return password;

}

@Override

public String getUsername() {

// TODO Auto-generated method stub

return username;

}

@Override

public boolean isAccountNonExpired() {

return true;

}

@Override

public boolean isAccountNonLocked() {

return false;

}

@Override

public boolean isCredentialsNonExpired() {

return true;

}

@Override

public boolean isEnabled() {

return true;

}

public String getProviderId() {

return providerId;

}

public void setProviderId(String providerId) {

this.providerId = providerId;

}

public void setUsername(String username) {

this.username = username;

}

public void setAuthorities(Collection<GrantedAuthority> authorities) {

this.authorities = authorities;

}

public void setPassword(String password) {

this.password = password;

}

ClientUserDetailsService.java

package org.ikane.security;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import org.ikane.service.AccountService;

import org.pac4j.springframework.security.authentication.ClientAuthenticationToken;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.authority.SimpleGrantedAuthority;

import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class ClientUserDetailsService implements AuthenticationUserDetailsService<ClientAuthenticationToken> {

private AccountService accountService;

public UserDetails loadUserDetails(final ClientAuthenticationToken token) throws UsernameNotFoundException {

Map account = accountService.lookupAccountByProvider(token.getClientName(), token.getUserProfile().getId());

//String username = account.containsKey(“displayName”) ? account.displayName : “”

String username = “admin”;

final List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

for (String role: token.getUserProfile().getRoles()) {

authorities.add(new SimpleGrantedAuthority(role));

}

if (!account.isEmpty() && authorities.isEmpty()) {

// default to user role

authorities.add(new SimpleGrantedAuthority(“ROLE_USER”));

}

return new ClientUserDetails(username, token.getUserProfile().getId(), authorities);

}

public AccountService getAccountService() {

return accountService;

}

public void setAccountService(AccountService accountService) {

this.accountService = accountService;

}

AccountService.java

package org.ikane.service;

import java.util.HashMap;

import java.util.Map;

import org.springframework.stereotype.Service;

@Service

public class AccountService {

/**

* @Autowired

JdbcTemplate jdbcTemplate

* */

public Map lookupAccountByProvider(String providerName, String providerUserId) {

HashMap<Object,Object> map = new HashMap<>();

/**

*

List results = jdbcTemplate.query(

“select * from account where provider = ? and provider_user_id = ?”,

[providerName, providerUserId] as Object[],

new GenericRowMapper()

)

if (results.size() > 1) {

throw new Exception(“multiple accounts by provider [${providerName}] for id [${providerUserId}]”)

}

* **/

return map;

}

public Boolean createAccountForProvider(String providerName, String providerUserId, String displayName) {

/**

* log.debug(“creating new account for displayName=${displayName} using provider=${providerName} with id ${providerUserId}”)

int result = jdbcTemplate.update(

“insert into account (display_name, provider, provider_user_id) values (?, ?, ?)”,

displayName,

providerName,

providerUserId

)

if (result != 1) {

log.warn(“creation of account for provider [${providerName}] and id [${providerUserId}] failed”)

return false

}

* */

return true;

}

}

index.html

<!doctype html>

<html xmlns:th=”http://www.thymeleaf.org”>

<head>

<title>Spring Pac4j Demo</title>

</head>

<body>

<h2>Index Page sgdsfg</h2>

</body>

</html>123456789

login.html

<!doctype html>

<html xmlns:th=”http://www.thymeleaf.org”

xmlns:layout=”http://www.ultraq.net.nz/thymeleaf/layout”

layout:decorator=”layouts/default”>

<head>

<title>Login</title>

</head>

<body>

<div id=”content” class=”sign-in-page” layout:fragment=”content”>

<h2>Sign In</h2>

<a th:href=”${casAuthUrl}” th:class=”‘oauth-login-link cas-login'”>CAS</a>

<a th:href=”${gitHubAuthUrl}” th:class=”‘oauth-login-link github-login'”>GitHub</a>

<a th:href=”${google2AuthUrl}” th:class=”‘oauth-login-link google-login'”>Google</a>

<a th:href=”${twitterAuthUrl}” th:class=”‘oauth-login-link twitter-login'”>Twitter</a>

</div>

</body>

</html>


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design for Hackers

Design for Hackers

David Kadavy / Wiley / 2011-10-18 / USD 39.99

Discover the techniques behind beautiful design?by deconstructing designs to understand them The term ?hacker? has been redefined to consist of anyone who has an insatiable curiosity as to how thin......一起来看看 《Design for Hackers》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具